Ajax基础
1 Ajax概述
- 是浏览器提供的一套方法,可以实现页面无刷新更新数据,提高用户浏览网站体验。
2 Ajax应用场景
- 页面上拉加载更多数据。
- 列表数据无刷新分页。
- 列表项离开焦点数据验证。
- 搜索框提示文字下拉列表。
3 Ajax运行环境
- Ajax技术需要运行在网站环境中才能生效。
const express = require('express');
const path = require('path');
const app = express();
//实现静态资源访问功能 开启静态资源文件
app.use(express.static(path.join(__dirname,'public')));
//也可以添加一个虚拟路径
//app.use('static' , express.static(path.join(__dirname,'public')));
app.listen(3000,()=>{
console.log('ok');
});
4 Ajax运行原理及实现
4.1 运行原理
- Ajax相当于浏览器发送请求与接收响应的代理人。在不影响用户浏览页面的情况下刷新数据。
4.2 实现步骤
-
创建Ajax对象。
var xhr = new XMLHttpRequest();
-
告诉Ajax请求方式和请求地址。
xhr.open('get','http://suchas.com');
-
发送请求。
xhr.send();
-
获取服务器端给客户端的响应数据。
//方式一 xhr.onload = ()=>{ console.log(xhr.responseText); } //方式二 xhr.onreadystatechange = function(){ consoloe.log(xhr.readyState); //响应状态码 if(xhr.readyState == 4){ console.log(xhr.responseText); } }
4.3 服务器响应的数据格式
- 项目中,服务器端大多数会以JSON对象作为响应数据的格式。
- 在HTTP请求与响应的过程中,无论是请求参数还是响应内容,若是对象类型,最终都会转换成对象字符串进行传输。
<script>
//1、创建Ajax对象
var xx = new XMLHttpRequest();
// 2、告诉Ajax请求地址以及请求方式(请求方式、请求地址)
xx.open('get', 'http://localhost:3000/responseData');
// 3、发送请求。
xx.send();
// 4、获取服务器端给客户端的响应数据。
xx.onload = function () {
//服务器端响应数据
console.log(xx.responseText);
console.log(typeof xx.responseText); //string
var responseText = JSON.parse(xx.responseText)
console.log(responseText); //{name: "张三"}
var str = '<h1>' + responseText.name + '</h1>';
document.body.innerHTML = str; //张三
}
</script>
const express = require('express');
const path = require('path');
const app = express();
//实现静态资源访问功能 开启静态资源文件
app.use(express.static(path.join(__dirname,'public')));
app.get('/responseData',(req,res) => {
res.send({'name':'张三'});
});
app.listen(3000,()=>{
console.log('服务器启动');
});
4.4 请求参数传递
- 传统网站使用表单传递。
- 根据表单请求方式不同分两种:GET、POST。表单内容会变成请求参数自动拼接到相对应位置。
- GET请求参数,会被拼接到请求地址后面。
- POST请求参数,会被放到请求体当中。
- 格式都为:跟在?后面,参数名称=参数值,多个参数用 & 连接。
4.4.1 GET请求参数
req.query
返回get请求的参数。
get请求参数/
const express = require('express');
const path = require('path');
const app = express();
//实现静态资源访问功能 开启静态资源文件
app.use(express.static(path.join(__dirname,'public')));
//设置路由
app.get('/get',(req,res) => {
res.send(req.query);
});
app.listen(3000,()=>{
console.log('服务器启动');
});
<div class="box">
<input type="text" name="username" class="un">
<input type="text" name="age" class="pw">
<button class="btn">提交</button>
</div>
<script>
document.querySelector('.btn').onclick = function () {
var xx = new XMLHttpRequest();
var un = document.querySelector('.un').value;
var pw = document.querySelector('.pw').value;
var params = 'username=' + un + '&age=' + pw;
xx.open('get', 'http://localhost:3000/get?' + params);
xx.send();
xx.onload = function () {
console.log('JSON\t' + xx.responseText); //JSON
console.log(JSON.parse(xx.responseText)); //对象
}
};
</script>
4.4.2 POST请求参数
- 请求报文:
- 在HTTP请求和响应的过程中传递的数据块就是报文,包括传送的数据和一些附加的信息,并遵守规定好的格式。
- 分为报文头和报文体。
- 报文头存储的是键值对信息。
- 报文体存储内容。
- post请求必须在请求报文中明确设置请求参数内容的类型(报文属性)。
xx.setRequestHeader();
- 在服务器端接收post请求参数,借助第三方模块
body-parser
,然后用res.send(req.body)
获取客户端传递到服务器端的post请求参数。app.use(bodyParser.urlencoded());
接收post请求参数,返回解析body中字符的中间件。- bodyParser.json()接受json请求;bodyParser.urlencoded()接受json请求,二者解析规则不同。
- bodyParser.json(参数)。
- 参数可选,方法返回一个仅用来解析json格式的中间件。这个中间件能接受任何body中任何Unicode编码的字符。支持自动的解析gzip和 zlib。
- bodyParser.urlencoded(参数)。
- 参数可选,方法返回一个中间件,这个中间件用来解析body中的urlencoded字符, 只支持utf-8的编码的字符。同样也支持自动的解析gzip和 zlib。
- urlencoded方法的extended参数说明:
- extended: false:表示使用系统模块querystring来处理,官方推荐的。
- extended: true:表示使用第三方模块qs来处理。
const express = require('express');
const path = require('path');
//在服务器端接收post请求参数借助第三方模块,然后用req.body获取客户端传递到服务器端的post请求参数
const bodyParser = require('body-parser');
const app = express();
//接收post请求参数,返回解析body中字符的中间件
app.use(bodyParser.urlencoded());
app.use(express.static(path.join(__dirname,'public')));
请求post参数
app.post('/post',(req,res) => {
// 1、借助第三方模块body-parser
// 2、req.body获取客户端传递到服务器端的请求参数
// 3、由res.send响应回客户端
res.send(req.body);
});
app.listen(3000,()=>{
console.log('服务器启动');
});
<div class="box">
<input type="text" name="username" class="un">
<input type="text" name="age" class="pw">
<button class="btn">提交</button>
</div>
<script>
document.querySelector('.btn').onclick = function () {
var xx = new XMLHttpRequest();
var un = document.querySelector('.un').value;
var pw = document.querySelector('.pw').value;
var params = 'username=' + un + '&age=' + pw;
xx.open('get', 'http://localhost:3000/post');
// 设置请求参数格式类型(POST请求必须设置) 固定格式
xx.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
// 发送请求 放到请求体
xx.send(params);
xx.onload = function () {
console.log('JSON\t' + xx.responseText); //JSON
console.log(JSON.parse(xx.responseText)); //对象
}
};
</script>
4.4.3 请求参数格式
-
设置请求参数格式类型:告诉服务器当前请求参数的格式。
xx.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
-
application/x-www-form-urlencoded
name=zhangsan&age=20&sex=女
-
application/json
{name:'zhangsan',age:'20',sex:女}
注意:
- get请求不能提交JSON对象数据格式。只能使用application/x-www-form-urlencoded的参数格式进行传递。
- 传统网站的表单提交也不支持JSON对象数据格式。默认也是跟get一样使用application/x-www-form-urlencoded进行传递。
-
参数必须以字符串的形式传递。
JSON.stringify(); //JSON对象转换为JSON字符串 //parse用于从一个字符串中解析出json对象
4.5 获取服务器端的响应
4.5.1 Ajax响应状态码
-
创建Ajax对象==>配置Ajax对象==>发送请求==>接收服务器响应数据。此过程中的每一个步骤都会对应一个数值,即Ajax状态码。
-
通过readyState前端请求状态码,可以获知当前请求进行到哪一个步骤。
- **0:请求未初始化。**即已创建Ajax对象,但还未对其进行配置(尚未调用open()方法)。
- **1:请求已建立。**即已调用open()方法配置Ajax对象,但还没发送请求(尚未调用send()方法)。
- **2:请求已发送。**即已经调用了send()方法。
- **3:请求正在处理中。**即通常已经接收到部分数据,正在接收服务器端响应的数据。
- **4:响应已经完成。**可以获取并使用服务器的响应。
- **0=>1=>2=>3=>4理解:**未建立=>已建立=>请求发送=>请求处理=>请求就绪、响应完成
4.5.2 xhr.readyState属性
-
ajax对象的xhr.readyState属性用来获取响应状态码
var xhr = new XMLHttpRequest();
xhr.readyState //获取响应状态码
4.5.3 onload事件
-
只有处于状态码4,请求已完成,响应已就绪的情况下,才会进入onload。
-
只要进入onload请求中,一定是已经到4这个状态了。
-
但是进入onload状态之后的响应状态码就不确定了,当请求地址输入错误时,也可能会进入onload状态
xhr.onload = function(){ console.log("readyState="+ xhr.readyState); console.log(this.responseText); }
4.5.4 onreadystatechange事件
- 当Ajax状态码发生改变时,自动触发此事件。
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded());
app.use(express.static(path.join(__dirname,'public')));
app.post('/post',(req,res) => {
res.send(req.body);
});
app.listen(3000,()=>{
console.log('服务器启动');
});
<div class="box">
<input type="text" name="username" class="un">
<input type="text" name="age" class="pw">
<button class="btn">提交</button>
</div>
<script>
document.querySelector('.btn').onclick = function () {
var xx = new XMLHttpRequest();
var un = document.querySelector('.un').value;
var pw = document.querySelector('.pw').value;
var params = 'username=' + un + '&age=' + pw;
xx.open('get', 'http://localhost:3000/post');
xx.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xx.send(params);
/*xx.onload = function () {
console.log('JSON\t' + xx.responseText); //JSON
console.log(JSON.parse(xx.responseText)); //对象
}*/
xx.onreadystatechange = function(){
consoloe.log(xx.readyState); //状态码
if(xx.readyState == 4){
console.log(xx.responseText);
}
}
};
</script>
4.5.5 两种获取服务器端响应方式区别
区别 | onload事件 | onreadystatechange |
---|---|---|
是否兼容低版本IE | 否 | 是 |
是否需要判断状态码 | 否 | 是 |
调用次数 | 1次 | 多次 |
4.6 Ajax错误处理
- 网络畅通,服务器端能接收请求,服务器端返回的结果不是预期结果。
- 可以判断服务器端返回的状态码,分别进行处理。xhr.status获取http状态码。
- 网络畅通,服务器端没有接收到请求,返回404状态码。
- 可以检查请求地址是否错误。
- 网络畅通,服务器端能接收请求,服务器端返回500状态码。
- 服务器端发生错误,可以与后端开发人员沟通。
- 网络中断,请求无法发送到服务器端。
- 会触发xhr对象下面的onerror事件,在事件处理函数中对错误进行处理。
4.6.1 HTTP状态码
- http状态码:表示请求的处理结果,是服务器端返回的。
- Ajax状态码:表示Ajax请求的过程状态,Ajax对象返回的。
4.6.2 低版本IE的缓存问题
-
问题:低版本IE中,Ajax请求有严重的缓存问题。即请求地址不变的情况下,只有第一次请求会真正的发送到服务器端,之后的请求都会从IE缓存里面拿数据。即使服务器端的数据更新,客户端拿到的依旧是缓存中的旧数据。
-
解决方案:在请求地址的后面加请求参数,保证每一次请求中的请求参数值都不相同。
xhr.open('get','http://www.suchas.com?n=' + Math.random());
5 Ajax异步编程
5.1 同步异步概述
-
同步
- 一行代码执行完之后才能执行后面的代码。
-
异步
-
程序不会等待异步代码执行完再继续执行后续代码,而是直接执行后续代码。后续代码执行完成后再回头看异步代码执行情况,若又返回结果,就调用事先准备好的回调函数处理异步代码执行的结果。
console.log(111); setTimeout(()=>{ console.log(333); },2000); console.log(222); //执行顺序:111 222 333
-
5 Ajax异步编程
5.1 同步异步概述
-
同步
- 一行代码执行完之后才能执行后面的代码。
-
异步
-
程序不会等待异步代码执行完再继续执行后续代码,而是直接执行后续代码。后续代码执行完成后再回头看异步代码执行情况,若又返回结果,就调用事先准备好的回调函数处理异步代码执行的结果。
console.log(111); setTimeout(()=>{ console.log(333); },2000); console.log(222); //执行顺序:111 222 333
-