AJAX
1.AJAX的特点
1.优点
- 可以无需刷新页面而与服务器端进行通信
- 允许你根据用户事件来刷新部分页面内容
2.缺点
- 没有浏览历史,不能回退
- 存在跨域问题
- SEO(搜索引擎优化)不友好 --> 爬虫不可爬取Ajax请求得来的数据
2.HTTP协议
1.http
超文本传输协议,规定了浏览器和万维网服务器之间相互通信的规则
2.请求报文
-
请求行:
- 请求类型:post、delete、put、get四种方式分别对应对数据的增删改查
- URL路径
- HTTP协议版本
-
请求头:
- Host:bilibili.com
- Cookie:name=hgg
- Content-type:application/x-www-form-urlencoded
- User-Agent:Chrome 83
-
请求空行:必须要有
-
请求体
-
如果是get请求,请求体为空
-
如果是post请求,请求体可以不为空 e.g–>username=admin&password=admin
-
3.响应报文
- 响应行:
- HTTP协议版本
- 响应状态码:200、404、403、500、401等
- 响应状态字符串:与状态码对应
- 响应头:
- Content-type:text/html;charset=utf-8
- Content-length:2048
- Content-encoding:gzip
- 响应空行:必须要有
- 响应体:响应的数据内容
3.原生Ajax
1.ajax中的get请求
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>click</button>
<div class="content"></div>
</body>
<script>
document.querySelector('button').onclick=function(){
let xhr=new XMLHttpRequest();
xhr.open('GET','http://localhost:3000/ajax');
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200&&xhr.status<300){
console.log(xhr)
document.querySelector('.content').innerHTML=xhr.responseText;
}
}
}
}
</script>
</html>
服务器代码
let express=require('express');
let app=express();
app.get('/ajax',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*')
res.send('232323')
})
app.listen(3000)
请求结果
2.ajax中的get请求携带参数
后缀在URL之后,用 ? 分割路径与参数键值对,e.g:
xhr.open('GET','http://localhost:3000/ajax?name=2233&pass=cdd');
3.ajax中的post请求
写法与get方式大致相同,变化的地方在于
//前台代码变化
xhr.open('POST','http://localhost:3000/ajax?name=2233&pass=cdd');
//后台代码变化
app.post('/ajax',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*')
res.send('232323')
})
传递请求体参数设置在xhr.send中,e.g:
xhr.send('user=333333&agent=chrome');
请求结果
4.设置请求头
xhr中的setRequestHeader方法,接收两个参数,头的名字和头的值,同样可以在network中查看
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
请求结果
5.服务器响应json数据
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>click</button>
<div class="content"></div>
</body>
<script>
document.querySelector('button').onclick=function(){
let xhr=new XMLHttpRequest();
xhr.open('GET','http://localhost:3000/json');
xhr.responseType='json';//设置响应体类型,将自动进行数据格式的转换
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
if(xhr.status>=200&&xhr.status<300){
console.log(xhr)
for (const xhrKey in xhr.response) {
let div=document.createElement('div');
div.innerHTML=`${xhrKey}------${xhr.response[xhrKey]}`;
document.body.appendChild(div);
}
}
}
}
}
</script>
</html>
服务器代码
let express=require('express');
let app=express();
app.get('/json',(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*')
let user={
name:'cdd',
age:24,
hobbies:'hiahiahihaiahiahia'
}
res.json(user);//向客户端响应json数据
})
app.listen(3000)
6.IE浏览器缓存问题
-
IE缓存开启之后,会对ajax的数据进行缓存,有时会导致页面不能及时更新
-
解决方法:在URL路径最后加上时间戳,e.g
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>click</button>
<div class="content"></div>
</body>
<script>
document.querySelector('button').onclick=function(){
let xhr=new XMLHttpRequest();
//设置时间戳
xhr.open('GET','http://localhost:3000/json?t='+Date.now());
xhr.responseType='json';//设置响应体类型,将自动进行数据格式的转换
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
if(xhr.status>=200&&xhr.status<300){
console.log(xhr)
for (const xhrKey in xhr.response) {
let div=document.createElement('div');
div.innerHTML=`${xhrKey}------${xhr.response[xhrKey]}`;
document.body.appendChild(div);
}
}
}
}
}
</script>
</html>
7.Ajax请求超时与网络异常处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>click</button>
<div class="content"></div>
</body>
<script>
document.querySelector('button').onclick=function(){
let xhr=new XMLHttpRequest();
xhr.timeout=2000;//超时设置,当在设置的时间段内没有收到来自服务器的响应报文,就取消发送此次ajax请求
xhr.ontimeout=function(){//监听超时的函数
alert('请求超时')
}
xhr.onerror=function(){//监听网络错误的函数,想要看见效果可以在Chrome调试器中的network把网络状态offline后,再发送请求
alert('网络错误')
}
xhr.open('POST','http://localhost:3000/ajax?name=2233&pass=cdd');
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('user=333333&agent=chrome');
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200&&xhr.status<300){
console.log(xhr)
document.querySelector('.content').innerHTML=xhr.responseText;
}
}
}
}
</script>
</html>
超时的请求结果
网络错误的请求结果
8.Ajax取消请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="btn1">start</button>
<button class="btn2">cancel</button>
</body>
<script>
let xhr=new XMLHttpRequest();
document.querySelector('.btn1').onclick=function(){
xhr.open('GET','http://localhost:3000/ajax');
xhr.send();
xhr.onreadystatechange=function(){
}
}
document.querySelector('.btn2').onclick=function(){
xhr.abort();//核心代码,调用xhr的abort方法取消发送ajax请求
}
</script>
</html>
9.多次发送ajax请求的处理方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>click</button>
</body>
<script>
let isSending=false;//定义全局变量标志ajax请求是否正在发送
let xhr;
document.querySelector('button').addEventListener('click',function(){
if(isSending)//第一次点击按钮不执行,从第二次开始,会执行该语句,取消上一次ajax请求的发送,避免给服务器造成过大压力
xhr.abort();
xhr=new XMLHttpRequest();
xhr.open('GET','http://localhost:3000/ajax');
xhr.send();
isSending=true;//标志正在发送ajax请求
xhr.onreadystatechange=function(){
if(xhr.readyState===4){
isSending=false;//ajax请求发送结束
}
}
})
</script>
</html>
4.jQuery发送ajax请求
. g e t 或 者 .get或者 .get或者.post方法:
- 第一个参数为URL地址,
- 第二个参数是一个对象,用于传递数据
- 第三个参数为回调函数,对响应数据做处理
- 第四个参数为响应体类型,非必填,填入json后可以将服务器返回的json字符串转换为json对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>send get</button>
<button>send post</button>
</body>
<script src="./jquery.js"></script>
<script>
$('button').eq(0).click(function(){
$.get('http://localhost:3000/json',{a:100,b:999},function(data){
//第二个参数中的数据将以查询字符串的方式发送给服务器
console.log(data)
},'json')
})
$('button').eq(1).click(function(){
$.post('http://localhost:3000/json',{a:100,b:999},function(data){
//第二个参数中的数据将以formData的格式发送给服务器
console.log(data)
})
})
</script>
</html>
请求结果
jQuery通用方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>send</button>
<button>send post</button>
</body>
<script src="./jquery.js"></script>
<script>
$('button').eq(0).click(function (){
$.ajax({
url:'http://localhost:3000/json',//请求路径
type:'POST',//请求方式
data:{//请求报文中所携带的数据
name:'cdd',
pass:'232sdffgs'
},
dataType:'json',//服务器响应的数据格式
success:function(data){//发送请求成功的回调函数
console.log(data)
},
timeout:2000,//设置超时时间
error:function(){//发送请求错误的回调函数
console.error('出错啦')
},
headers:{//设置请求头
Authorization:'sswer2q423rfsdfsasf'
}
})
})
</script>
</html>
5.使用axios发送请求
- axios.get
- 第一个参数是URL路径
- 第二个参数是一个对象,其中
- params对象,其中存放URL参数
- headers对象,其中设置请求头信息
- 最后基于promise在then中接收服务器的响应数据
- axios.post
- 第一个参数是URL路径
- 第二个参数是一个对象,其中存放请求体数据
- 第三个参数是一个对象,其中
- params对象,其中存放URL参数
- headers对象,其中设置请求头信息
- 最后基于promise在then中接收服务器的响应数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button class="btn1">send get</button>
<button class="btn2">send post</button>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
document.querySelector('.btn1').addEventListener('click',function(){
axios.get('http://localhost:3000/json',{
params:{
userId:2323,
courseId:2323
},headers:{
Authorization:'43434dfdfdf'
}
}).then((res)=>{
console.log(res)
})
})
document.querySelector('.btn2').addEventListener('click',function(){
axios.post('http://localhost:3000/json',{
name:'admin',
pass:'admin'
},{
params:{
userId:2323,
courseId:2323
},headers:{
Authorization:'43434dfdfdf',
'Content-Type':'application/x-www-form-urlencoded'
}
}).then((res)=>{
console.log(res)
})
})
</script>
</html>
axios通用方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>send</button>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
document.querySelector('button').onclick=function(){
axios({
url:'http://localhost:3000/json',//URL路径
method:'POST',//请求方式
params:{//URL参数
userId:22,
courseId:33
},
headers:{//设置请求头
Authorization:'232dsdsdssd',
'Content-Type':'application/x-www-form-urlencoded'
},
data:{//请求体数据
name:'alice',
pass:'cddalice'
}
}).then((res)=>{//发送成功后的回调函数
console.log(res)
})
}
</script>
</html>
6.fetch发送请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>send</button>
</body>
<script>
document.querySelector('button').onclick=function(){
fetch('http://localhost:3000/json',{
method:'POST',
headers:{
Authorization:'werw232323',
'Content-Type':'application/x-www-form-urlencoded'
},
body:'name=admin&pass=admin'//请求体数据
}).then(res=>{//此时res是一个promise对象,需要转换一下才能取值
return res.json()
}).then((res)=>{
console.log(res)
})
}
</script>
</html>
7.跨域
1.Ajax同源策略
- 同源:协议、域名和端口号必须完全相同
- 同源策略是浏览器而定一种安全策略,违反同源策略就是跨域
2.如何解决跨域
-
jsonp解决跨域原理
-
ajax响应的返回结果是函数调用,而函数的实参就是我们想给客户端返回的结果数值,而这个函数必须先在客户端定义好
-
原生jsonp实践
-
<!--前端代码--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button>click</button> <div></div> </body> <script> let btn= document.querySelector('button') let div=document.querySelector('div') function handle(data){ btn.style.border='red'; div.innerHTML=data.name } btn.onclick=function(){ let script=document.createElement('script')//设置script标签 script.src='http://localhost:3000/jsonp'//设置src属性 document.body.appendChild(script);//将script标签嵌入文档 } </script> </html>
-
//服务器代码 let express=require('express'); let app=express(); app.all('/jsonp',(req,res)=>{ res.setHeader('Access-Control-Allow-Origin','*') res.setHeader('Access-Control-Allow-Headers','*') let user={ name:'cdd', age:24, hobbies:'hiahiahihaiahiahia' } res.end(`handle(${JSON.stringify(user)})`); }) app.listen(3000)
-
-
jQuery发送jsonp请求
-
URL地址之后必须加上一个?callback=?(固定格式),之后jQuery会自动在callback之后加上一个字符串,将作为函数名在后端使用
-
<!--前端代码--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button>send</button> <div class="inner"></div> </body> <script src="./jquery.js"></script> <script> $('button').click(function(){ $.getJSON('http://localhost:3000/jsonp2?callback=?',function(res){ $('.inner').html( `姓名----${res.name}<br> 年龄----${res.age}` ) }) }) </script> </html>
-
后端接收callback参数,并发送回前端页面,jQuery会处理并返回res值
-
//服务器代码 let express=require('express'); let app=express(); app.all('/jsonp2',(req,res)=>{ res.setHeader('Access-Control-Allow-Origin','*') res.setHeader('Access-Control-Allow-Headers','*') let user={ name:'cdd', age:24, hobbies:'hiahiahihaiahiahia' } res.end(`${req.query.callback}(${JSON.stringify(user)})`); }) app.listen(3000)
-
-