ajax就是异步的JS和XML
通过ajax可以在浏览器中向服务器发送异步请求,其最大的优势就是无刷新获取数据
ajax是一种将现有标准组合在一起使用的新方式
可以无刷新情况下向服务器发送请求,进行通信
允许根据用户事件来部分更新页面内容
没有浏览历史,不能回退
存在跨域问题
SEO不友好
XML是可扩展标记语言
被用来传输和储存数据
与HTML相似,但HTML中都是预定义标签,而XML中没有预定义标签,全部都是自定义标签,用来表示一些数据
现在已经被json替代了。上面的数据用Jason表示:{'name':'孙悟空','age':18,'gender':'男'}
HTTP协议是超文本传输协议,其规定了浏览器和万维网服务器之间互相通信的规则
浏览器向服务器发送的内容被称之为请求报文,服务器向浏览器发送的结果被称为响应报文
包括四部分:请求行、请求头、空行、请求体
包括三部分:请求类型(get\post等)、URL路径、HTTP协议版本
Host、Cookies、Content-type等,格式:名字: 值
空行是固定的,必须有
请求体可以有也可以没有,get请求中没有请求体
包括四部分:返回行、返回头、空行、返回体
包括HTTP协议版本、响应状态码、响应状态字符串(和相应状态码对应)三部分
格式和请求报文中格式一样
空行是固定的,必须有
主要的返回结果
由于使用ajax需要服务器,为了便于之后的学习,这里使用express框架
//引入express
const { request, response } = require('express')
const express=require('express')
// 创建应用对象
const app=express()
// 创建路由规则
// request是对请求报文的一个封装
// response是对响应报文的一个封装
app.get('/',(request,response)=>{
// 设置响应
response.send('hello!')
})
// 监听端口启动服务
app.listen(8000,()=>{
console.log('服务已启动,8000端口监听中')
})
服务端代码:
const express=require('express')
const app=express()
// /server表示如果请求行的URL路径是/server时,会执行后面的回调函数
app.get('/server',(request,response)=>{
// 设置响应头,设置允许跨域
response.setHeader('Access-Control-Allow-Origin','*')
// 响应体
response.send('hello ajax!')
})
app.listen(8000,()=>{
console.log('服务已启动,8000端口监听中')
})
发送ajax请求并将响应体显示在页面上
Document
get请求没有请求体,所以在URL后使用?参数名=参数值来设置请求参数,并且使用&连接参数
如:http://www.baidu.com/server?name=admin&b=8326&c=832
//创建对象
const xhr=new XMLHttpRequest();
// 初始化,设置请求方法和url
xhr.open('POST','http://127.0.0.1:8000/server')
// 发送
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
if(xhr.status>=200 && xhr.status<300){
result.innerHTML=xhr.response
}
}
}
注意,服务器端也要设置响应post请求的方法:
app.post('/server',(request,response)=>{
response.setHeader('Access-Control-Allow-Origin','*')
response.send('hello ajax!')
})
在send中设置,例如:xhr.send('a=100&b=200&c=300')
只需要在open方法调用之后加上一个setRequestHeader()方法
例:
xhr.open('GET','http://127.0.0.1:8000/server')
// 设置请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
//Content-Type是用来设置请求体内容的类型
实际情况中,浏览器向服务器发送请求,服务器大多时候返回的是json数据,此时,就需要了解如何处理json格式的数据
方法一:手动对数据进行转换,例如:let data=JSON.parse(xhr.response),将json格式的数据转化为对象格式
方法二:自动转换,在open方法调用之前设置响应体数据类型为json:xhr.responseType='json',然后返回的json格式数据会自动转化为对象类型
IE浏览器会对ajax请求的结果进行缓存,当下一次发出一样的ajax请求时,IE浏览器会取出缓存的数据返回,而不是最新的从服务器获取的数据,这在数据具有时效性时会造成影响
解决方法:在url后加上?t='Date.now()
例如:xhr.open('POST','http://127.0.0.1:8000/server?t='+Date.now())
有时因为网络等原因,请求发出后,在一段时间内都没有收到响应,这个时候需要进行处理
网络异常时,也需要处理
...
const xhr=new XMLHttpRequest()
//两秒之后如果没有收到响应,就取消请求
xhr.timeout=2000
//超时回调,超时之后调用函数
xhr.ontimeout=function(){
alert('网络异常,请稍后重置')
}
//网络异常的回调,网络异常时调用函数
xhr.onerror=function(){
alert('网络出问题了')
}
...
在响应还没有接收之前,可以取消请求
可以使用abort方法:xhr.abort()
有时浏览器会重复向服务器发送一样的请求,这可能会导致服务器堵塞
解决方法:在发送请求之前查看之前有没有相同请求
...
//点击按钮,发送请求,如果之前存在相同请求,则不发送
let xhr
// 标志变量,检验是否正在发送相同请求
let isSending=false;
btn.onclick=function(){
// 判断标志变量,如果之前有相同请求,则直接返回
if(isSending) return
xhr=new XMLHttpRequest();
// 修改标识变量的值
isSending=true
xhr.open('GET','http://127.0.0.1:8000/server')
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send();
xhr.onreadystatechange=function(){
if(xhr.readyState==4){
// 修改标识变量的值
isSending=false
if(xhr.status>=200 && xhr.status<300){
result.innerHTML=xhr.response
}
}
}
}
...
...
//按下按钮,发送get请求,并在控制台输出响应体
$('.button2').click(function(){
// 第一个是URL地址,第二个是请求参数(对象形式)
// 第三个参数是一个回调函数,其参数是响应体
// 第四个参数表示响应体类型
$.get('http://127.0.0.1:8000/jquery',{a:100,b:200},function(data){
console.log(data)
},'json')
})
...
和get方法类似,但是将$.get换为$.post
...
$('.button3').click(function(){
$.post('http://127.0.0.1:8000/jquery',{a:100,b:200},function(data){
console.log(data)
},'json')
})
...
...
$('.button4').click(function(){
// 参数是一个对象
$.ajax({
// url
url:'http://127.0.0.1:8000/jquery',
// 请求数据
data:{a:100,b:100},
// 请求类型
type:'GET',
// 设置响应体类型
dataType:'json',
// 成功的回调
// data表示响应体
success:function(data){
console.log(data)
},
// 超时时间
timeout:2000,
//失败的响应
error:function(){
alert('网络出问题了')
},
})
})
...
btn2.onclick=function(){
// get请求
axios.get('http://127.0.0.1:8000/axios',{
// 设置url参数,即请求参数
params:{
id:100,
vip:7,
},
// 设置请求头信息
Headers:{
name:'yes',
}
}).then(value=>{
// 输出的value是一个对象
// 包含data(响应体)
// 还有响应头、响应状态码等很多信息
console.log(value)
})
}
和get请求类似,将axios.get换为axios.post,并且除了设置URL参数,还能设置请求体,使用{参数名:参数值}来设置,作为axios.post的第二个参数,其余设置放在对象中,作为axios.post的第三个参数,第一个参数是URL地址
btn3.onclick=function(){
axios.post('http://127.0.0.1:8000/axios',{
a:100,
b:200,
},{
Headers:{
name:'yes',
}
}).then(value=>{
console.log(value)
})
}
和jQuery很像
btn4.onclick=function(){
axios({
method:'GET',
url:'http://127.0.0.1:8000/axios',
params:{
a:100,
b:200,
},
Headers:{
name:'yes',
},
}).then(value=>{
console.log(value)
})
}
使用上类似axios的通用方法
fetch函数有两个参数,第一个是URL地址,第二个是一个可选的配置项对象,包括所有对请求的设置,可选参数有method、header、body(请求体)等
浏览器的一种安全机制
同源:协议、域名、端口号必须完全相同
同源策略就是网页的URL和请求资源的URL必须是同源的
ajax默认遵守同源策略,违背同源策略就是跨域
解决跨域的办法:JSONP
JSONP是一个非官方的跨域解决方案,只支持get请求
JSONP利用script标签的跨域能力来实现跨域
动态的创建一个script 标签
var script = document.createElement("script");
设置script 的src,设置一个回调函数,在服务器代码中,设置返回体时,调用这个函数,函数的参数为要返回的数据
script.src = "http://localhost:8000/test";
function abc(data) {
alert(data.name);
}
将script 插入到文档中
document.body.appendChild(script);
省去了自定义回调函数的过程
...
...
var btn = document.getElementById('btn')
btn.onclick = function () {
$.getJSON("http://127.0.0.1:8000/jquery-jsonp?callback=?",function(data) {
console.log(data);
});
}
...
CORS,跨域资源共享,是官方的跨域解决方案,完全在服务器端实现。
CORS通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器接到该响应以后就会对响应放行
使用:
response.setHeader('Access-Control-Allow-Origin', '*')
response.setHeader('Access-Control-Allow-Method', '*')
response.setHeader('Access-Control-Allow-Headers', '*')