1、什么是Ajax?
Ajax,Asynchronous Javascript And XML ,即异步的js和xml。
在我们平时使用浏览器浏览网页时,以知乎、今日头条为例:
上图中,滑动鼠标滚轮时,会出现新的内容,但是页面并没有被刷新,这种无需刷新页面即可进行数据交互的技术,就是Ajax。
2、Ajax的优点:
1、无需刷新页面即可进行数据交互;
2、允许你根据用户事件来更新页面部分内容
第二点的展示,在20年的淘宝网站中,充话费的版块,就是使用的Ajax技术
这一块框出来的,就是使用的Ajax,用户在鼠标移动到充话费的Tab菜单时,提交请求,后台接收数据返回响应,里面的html文件构成了这个局部div的内容。
从上面的两个例子中我们可以看到,Ajax虽然叫异步的js和xml,实际上在现在的运用中,还是可以传输html的,除了xml和html之外,json也可以使用Ajax进行传输,详情可以参考:Ajax——三种数据传输格式 - Wayfo - 博客园
3、Ajax的缺点
1、没有浏览记录(因为本身是无页面刷新数据交互,所以不存在浏览记录,可以通过前端路由解决);
2、存在跨域问题;(后续整理)
3、SEO(搜索引擎优化)不友好。
4、使用原生Ajax请求数据
这里先用node.js模拟后台数据:
const express = require('express');
const app = express();
// 跨域解决方案
app.all('*',function(req,res,next){
res.header("Access-Control-Allow-Origin","*");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DE;ETE,OPTIONS");
res.header("Access-Control-Allow-Headers","X-Requester-With");
res.header("Content-Type","application/json;charset=utf-8");
next();
})
app.get('/',(req,res)=>{
console.log(req.query);
res.send("后台服务启动");
});
app.listen(8000,()=>{
console.log("后台服务监听启动, 端口:8000");
})
再使用前端页面,写一个原生的Ajax实例,通过按钮调用Ajax实例发送数据:
<body>
<form action="">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<button id='loginBtn'>登录</button>
<h4></h4>
</form>
<script>
document.getElementById('loginBtn').addEventListener('click',function(){
// 创建xhr实例对象
let xhr = new XMLHttpRequest();
// console.log(xhr.readyState); //打印0
// xhr内部有5种状态,值分别为0,1,2,3,4
// xhr实例对象,在实例出来的那一刻,状态就是0
// onreadystatechange 方法,会在xhr实例状态发生变更时执行
xhr.onreadystatechange=()=>{
// 函数体
// console.log("@"); //打印4次,分别在xhr实例的值0=>1=>2=>3=>4,这4次发生变化时调用本方法
// console.log(xhr.readyState);//使用readState可以打印xhr准备状态的值,当值为4时,表示整个请求过程完成
if(xhr.readyState === 4){
//打印“后台服务启动”,说明xhr实例成功接收到请求的响应了
console.log(xhr.response);
// xhr.status 状态码 ,通过if判断,当请求一切正常时,对html做改动
if(xhr.status>=200 && xhr.status<300){
document.getElementsByTagName('h4')[0].innerHTML = xhr.response;
// 可以在server.js文件中看到,res.send('后台服务启动')
}
}
}
// 指定发荣请求的method,url
xhr.open('GET','http://127.0.0.1:8000/');
// 发送请求
xhr.send();
})
</script>
</body>
原生Ajax的onreadystatechange方法体的内容,可以理解为:当请求的实例状态发生改变时要做什么;方法体里面的if分支,可以理解为:当请求的实例xhr对应的状态为0/1/2/3/4 时分别做什么,上面的代码块中只指定了当xhr实例状态码为4时要做什么。
4.1原生Ajax的属性和方法:
4.1.1 readState xhr实例状态信息
xhr.readState;
获取xhr实例的状态信息,有0/1/2/3/4 五种状态,当状态码为4时,表示该请求已经响应完成
4.1.2 onreadystatechange方法
onreadystatechange方法,会在xhr实例的readyState发生变化时自动执行
xhr.onreadystatechange();
onreadstatechange方法,当xhr实例刚刚被实例化时,其默认值为null,类型为object
使用方法:
xhr.onreadystatechange=()=>{
if(xhr.readyState === 0){
//当状态码为0时需要执行的内容
}else if(xhr.readyState === 1){
//当状态码为1时需要执行的内容
}else if(xhr.readyState === 2){
//当状态码为2时需要执行的内容
}else{
//当状态码为4时需要执行的内容,状态码为4时说明请求正常
}
}
4.1.3 status xhr实例状态码
xhr.status
// xhr实例的状态码,即Response Header 的状态码(200-500)信息
关于状态码,参考状态码200、300、400、500序列 - 孙氏楼 - 博客园
4.1.4 response xhr实例响应体
xhr.response
// 存放着xhr实例的响应信息,即nodejs里的res.send("这里面的内容")
5、jQuery封装的Ajax
使用jQuery封装的Ajax传参完整版:
$.ajax({
url:'http://127.0.0.1:8000/test_jquery_get', //请求地址
method:'GET', //请求方式,在调用参数中不写method时,默认会使用get的请求方式
data:{school:'atguigu'}, //携带数据
dataType:'json', //配置响应数据格式
success:(result,reponseText,a)=>{ //成功的回调
console.log(result);
content.append(`<div>汽车名:${result.name},价格:${result.price}
</div>`);//成功的回调
console.log(a); //js原生xhr对象
},
error:()=>{ //失败的回调
console.log('请求出错了!');
}
})
使用jQuery封装的Ajax传参精简版:
// jQuery请求精简版
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
},'json');
6、回调地狱
我们以jQuery的请求精简版解决下面的需求:点击一个按钮,在一个请求发送完毕后立马发送下一个请求,依次进行发送,假如我们需要发送5次:
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
$.get('http://127.0.0.1:8000/test_jquery_get',{school:'atguigu'},(data)=>{
console.log(data);
},'json');
},'json');
},'json');
},'json');
},'json');
通过上面的代码可以看到,这种因异步操作过多,依次回调的方式,后续的代码很难去进行维护,虽然这种代码在实现功能上没有什么缺点,但是对于程序员来说会变得很痛苦。这就是回调地狱。
针对回调地狱,我们可以使用promise来解决。