1. 初识Ajax
./public/Ajax.html
我是客户端
// 1. 创建Ajax对象
var xhr = new XMLHttpRequest();
// 2. 告诉Ajax对象向哪发送请求以及请求的方式
xhr.open('get','http://localhost:3000/first');
// 3. 发送请求
xhr.send();
// 4. 获取服务端响应给客户端的数据(` 当Ajax接收完服务端的响应之后,就会xhr的触发onload事件 `)
xhr.onload = function() {
console.log(xhr.responseText);
}
server.js
/*
传统网站中存在的问题:
网速慢的情况下,页面加载时间长,用户只能等待;
表单提交后,如果一项内容不合格,需要重新填写所有表单内容;
页面跳转,重新加载页面,造成资源浪费,增加用户等待时间;
*/
/*
AJax:
它是浏览器提供的一套方法,```可以实现页面无刷新更新数据```,提高用户浏览网站应用的体验;
应用场景:
.页面上拉加载更多数据;
.列表数据无刷新分页;
.表单项离开焦点数据验证;
.搜索框提示文字下拉列表;
*/
/*
Ajax的运行环境
Ajax技术需要运行在网站环境中才能生效,
当前课程会使用Node创建的服务器作为网站服务器;
*/
const express = require('express');
const path = require('path');
const app = express();
//静态资源的访问
app.use(express.static(path.join(__dirname, 'public')));
app.get('/first', (req, res) => {
res.send('Hello, Ajax!');
});
app.listen(3000, function () {
console.log('server is listening ... ... ');
});
2. 请求方式
./public/01_返回JSON对象.html
var xhr = new XMLHttpRequest();
xhr.open('get','http://localhost:3000/responseData');
xhr.send();
xhr.onload = function() {
// console.log(xhr.responseText); // "{"name": "ZhangSan"}": JSON字符串
// console.log(typeof(xhr.responseText)); // string
var obj = JSON.parse(xhr.responseText); // string => JSON对象 {"name": "ZhangSan"}
var str = '
' + obj.name + '
';document.body.innerHTML = str;
};
./public/02_传递get请求参数.html
var btn = document.getElementById('btn');
var username = document.getElementById('username');
var age = document.getElementById('age');
btn.onclick = function() {
var xhr = new XMLHttpRequest();
var nameValue = username.value;
var ageValue = age.value;
var params = 'username=' + nameValue + '&age=' + ageValue; // Ajax:自己拼接请求参数
xhr.open('get', 'http://localhost:3000/getArgs?' + params);
xhr.send();
xhr.onload = function() {
console.log(xhr.responseText);
}
}
./public/03_传递post请求参数.html
var btn = document.getElementById('btn');
var username = document.getElementById('username');
var age = document.getElementById('age');
btn.onclick = function () {
var xhr = new XMLHttpRequest();
var nameValue = username.value;
var ageValue = age.value;
var params = 'username=' + nameValue + '&age=' + ageValue;
xhr.open('post', 'http://localhost:3000/postArgs');
// 设置请求参数格式的类型(post请求必须设置请求头,get请求不需要)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// post请求参数一定要放在send中
xhr.send(params);
xhr.onload = function () {
console.log(xhr.responseText);
}
}
./public/04_请求参数的格式.html
var xhr = new XMLHttpRequest();
xhr.open('post', 'http://localhost:3000/json');
xhr.setRequestHeader('Content-Type', 'application/json'); // 客户端向服务器传递的请求参数格式为json
xhr.send(JSON.stringify({"name": "Zhang", "age": 14})); // 将JSON对象转换为json字符串(请求参数必须以字符串的形式进行传递)
xhr.onload = function() {
console.log(xhr.responseText);
};
/*
注意:get请求参数是不能提交JSON对象数据格式的, (只能提交application/x-www-form-urlencoded格式的数据)
传统网站的表单提交也是不支持JSON对象数据格式的!
*/
2.1 参数传递
server.js
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
/*
服务器端响应的数据格式:
在真实的项目中,服务器端大多数情况下会以JSON对象作为响应数据的格式;
当客户端拿到响应数据时,要将JSON数据和HTML字符串进行拼接;
然后将拼接的结果展示在页面中。
*/
/*
在http请求与响应的过程中,无论是请求参数还是响应内容,
如果是对象类型,最终都会被转换为对象字符串进行传输。
res.send({"name": "ZhangSan"});
如上, 服务器响应的是JSON对象, 但是会被转换为字符串进行传输,
所以在客户端接收的实际上"{"name": "ZhangSan"}",这是一个字符串,所以在客户端要进行转换, 将其转换成JSON对象!!!
*/
/*
1.application/x-www-form-urlencoded :
name=Zhang&age=23
===>
app.use(bodyParser .urlencoded());
```表示解析application/x-www-form-urlencoded格式的数据```
2.application/json :
{name: 'Zhang', age: '34', sex: 'man'}
===>
app.use(bodyParser.json());
```表示解析application/json格式的数据```
在请求头中指定Content-Type属性的值是application/x-www-form-urlencoded ,则是告诉服务器当前请求参数的格式是x-www-form-urlencoded(name=Zhang&age=23)!
在请求头中指定Content-Type属性的值是application/json,则是告诉服务器当前请求参数的格式是json({ name: 'Zhang', age:'23'})!
*/
//静态资源访问
app.use(express.static(path.join(__dirname, 'public')));
// 解析application/x-www-form-urlencoded数据格式(name='Zhang'&age=23)
app.use(bodyParser .urlencoded());
// responseData路由
app.get('/responseData', (req, res) => {
res.send({"name": "ZhangSan"}); // 响应JSON数据给客户端
});
// getArgs路由
app.get('/getArgs', (req, res) => {
res.send(req.query); // 响应给客户端
});
// postArgs路由
app.post('/postArgs', (req, res) => {
res.send(req.body);
});
app.use(bodyParser .json()); // 解析客户端发来application/json数据格式
// json路由
app.post('/json', (req, res) => {
res.send(req.body);
});
app.listen(3000, () => {
console.log(`Server started on port`);
});
2.2 Ajax状态码
test.html
var xhr = new XMLHttpRequest();
console.log(xhr.readyState); // 0 => 创建了Ajax对象
xhr.open('get', 'http://localhost:3000/readyState');
console.log(xhr.readyState); // 1 => 已经对AJax对象进行了配置
xhr.onreadystatechange = function () {
console.log(xhr.readyState);
// 2 => 请求已经发送
// 3 => 已经接收到服务端的部分数据了
// 4 => 服务端的响应数据已经接受完成
// 服务端的响应完成
if (xhr.readyState == 4) {
console.log(xhr.responseText);
}
}
xhr.send();
app.js
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(__dirname));
app.get('/readyState', (req, res) => {
res.send('请求结束');
})
app.listen(3000, () => {
console.log(`Server started on port`);
});
3. 错误处理
3.1 init
3.2 模拟测试
error.html
var btn = document.getElementById('btn');
btn.onclick = function () {
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:3000/error');
xhr.send();
xhr.onload = function () {
console.log(xhr.responseText);
if(xhr.status == 400) {
alert('请求出错');
}
};
// 网络中断触发onerror事件
// 模拟, offline, 然后点击按钮, 将触发此事件
xhr.onerror = function() {
alert('网络中断');
}
}
app.js
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(__dirname));
app.get('/error',(req, res) => {
// console.log(abc); // 此时服务端出错(输出了一个不存在的变量), 此时将返回400状态码给客户端
res.status(400).send('not ok');
});
app.listen(3000);
console.log('app start successful!');
4. Ajax缓存
4.1 init
4.2 测试 cache.html
var btn = document.getElementById('btn');
btn.onclick = function () {
var xhr = new XMLHttpRequest();
xhr.open('get', 'http://localhost:3000/cache');
// xhr.open('get', 'http://localhost:3000/cache?x=' + Math.random());
xhr.send();
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
}
app.js
const express = require('express');
const path = require('path');
const fs = require('fs');
const server = express();
server.use(express.static(__dirname));
server.get('/cache', (req, res) => {
fs.readFile('./test.txt',(err, result)=>{
res.send(result);
});
});
server.listen(3000);
console.log('server start successful!');
下图中的IE浏览器就会出现此问题。
好,采用上述的解决方案去解决该问题,结果如下图所示。
5. Ajax异步编程
init.html
var xhr = new XMLHttpRequest();
xhr.open('get','http://localhost:3000/first');
xhr.send();
xhr.onload = function() {
console.log('222222222');
console.log(xhr.responseText);
}
console.log('11111111');
/*
很明显:
11111111
222222222
22 Ok!
*/
app.js
const express = require('express');
const path = require('path');
const server = express();
server.use(express.static(__dirname));
server.get('/first', (req, res) => {
res.send('Ok!');
});
server.listen(3000, () => {
console.log('server start successful!');
});
6. Ajax封装
test.html
function ajax(options) {
// 存储的是默认值
var defaults = {
type: 'get',
url: '',
data: {},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: function() { },
error: function() { }
}
Object.assign(defaults, options);
//
var xhr = new XMLHttpRequest();
// 拼接get请求参数(name=Zhang&age=23))
var params = '';
for(var attr in defaults.data) {
params += attr + '=' + defaults.data[attr] + '&';
}
params = params.substring(0, params.length - 1); // name=Zhang&age=20&,去掉最后一个&
// 判断请求方式
if(defaults.type == 'get') {
defaults.url = defaults.url + '?' + params;
}
//
xhr.open(defaults.type, defaults.url); // 请求方式, 请求地址
//
if(defaults.type == 'post') {
var contentType = defaults.header['Content-Type']; // 请求参数类型
xhr.setRequestHeader('Content-Type', contentType);
if(contentType == 'application/json') {
xhr.send(JSON.stringify(defaults.data));
} else {
xhr.send(params);
}
} else {
xhr.send();
}
//
xhr.onload = function() {
// console.log(xhr.getResponseHeader('Content-Type')); //获取服务器端响应头的数据类型
var responseText = xhr.responseText;
if((xhr.getResponseHeader('Content-Type')).includes('application/json')) {
responseText = JSON.parse(xhr.responseText);
}
if(xhr.status == 200) {
defaults.success(responseText, xhr);
} else {
defaults.error(responseText, xhr);
}
};
}
// 调用函数
ajax({
type: 'post',
url: 'http://localhost:3000/index',
success: function(data, xhr) {
console.log('success()');
console.log(data);
console.log(xhr);
}
});
/*
请求参数要考虑的问题:
1.请求参数位置的问题
将请求参数传递到Ajax函数内部,在函数内部根据请求方式的不同将请求参数放置在不同的位置 ;
get 请求参数放在请求地址的后面; http://localhost/index?name=zhang&age=24
post 请求参数直接放在send方法中;
2. 格式问题
application/x-www-form-urlencoded (name=Zhang&age=24)
application/json ({"name": "Zhang", "age": "25"})
*/
app.js
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(__dirname));
app.get('/index', (req, res) => {
res.send('Ajax函数封装'); /* 此时响应头的数据类型是: text/html */
// res.send({"name": "Wang", "age": 23}); /* 此时响应头的数据类型是:application/json */
});
app.post('/index',(req, res) => {
// res.send("HelloWorld!!!!!!");
res.send({"name": "Wang", "age": 23});
});
app.listen(3000, () => {
console.log(`Server started on port`);
});
7. 浏览器模板引擎
init.html
{{username}} {{age}}
/* 以下操作相当于是将{username: ..., age: ...}对象中的值给渲染到tp1中相应的位置; 然后将渲染后的数据整体返回; */
var html = template
('tp1', {username: 'ZhangSan', age: 32});
// console.log(html); //
Zhang 32
document.getElementById('container').innerHTML = html;
8. Ajax案例
8.1 gitee地址
https://gitee.com/studyCodingEx/studys
8.2 效果演示
参考链接
发表评论