# 27、AJAX基础知识
什么是
AJAX
?async javascript and xml(异步的
JS
和XML
)客户端JS中的方法,用来向服务器端发送请求(还可以传递给服务器端数据),然后把服务器端返回的内容获取到(一般运行在客户端的浏览器中的)。
XML
:可扩展的标记语言(一种数据格式)利用自己扩展的有规则的标记来存储相关数据的
# 异步的JS
这里的异步不是说
AJAX
只能基于异步进行请求,这里的异步特指的是局部刷新
# 全局刷新
全局刷新
所谓的全局刷新就是页面中的每次数据更新,都会从服务器获取到最新的已经渲染好的源代码,然后拿到浏览器中进行展示;
[优势]
- 1)动态展示的数据在页面的源代码中可以看见,有利于SEO优化推广(有利于搜索引擎的收录和抓取)
- 2)从服务器获取的结果就已经是最后要呈现的结果了,不需要客户端做额外的事,所以页面加载速度快,(前提是服务器端处理的速度够快)如淘宝、京东的首屏数据一般都是由服务器端渲染
[弊端]
- 1)页面中的数据需要实时更新,即使是一张小图片更新,每次也都需要重新刷新一次。
- 2)都交给服务器端做数据渲染,服务器端的压力大,如果服务器处理不过来,页面呈现的速度更慢
- 3)全局刷新不利于开发(开发效率低)
# 局部刷新
局部刷新
前后端完全分离的项目,页面中需要动态绑定的数据是交给客户端完成渲染的:客户端渲染要以下步骤:
- 1、向服务器端发送AJAX请求
- 2、把从服务器端获取的数据解析处理,拼接成为我们需要展示的HTML字符串
- 3、拿拼接好的字符串替换页面中某一部分需要更新的内容(局部刷新),页面整体不需要重新加载,局部渲染即可
[优势]
- 1、我们可以根据需求,任意修改页面中某一部分内容(如实时刷新),整体页面不刷新,性能好,体验好(所有表单验证、需要实时刷新的需求都要基于AJAX实现)
-2、有利于开发,提高开发效率
- 1)前后端的完全分离,后台不需要考虑前端如何实现,前端也不需要考虑后台用什么技术,真正实现了前后端分离
- 2)可以同时开发:项目开发开始,先制定前后端数据交互的接口文档(文档中包含了调取哪个接口或者哪些数据等协议规范),后台把接口写好,客户端按照接口调取即可,后台再去实现接口功能即可;
[弊端]
- 1、不利于SEO优化:第一次从服务器端获取的内容不包含需要动态绑定的数据,不利于
SEO
收录,后期通过JS
添加到页面中的内容,并不会写到源代码中 - 2、由于需要动态绑定数据后,再交给浏览器渲染。所以没有服务器渲染页面呈现速度快;
# 基于原生JS实现AJAX
// Ajax四步:
let xhr=new XMLHttpRequest();
xhr.open("get","/data.txt",false);
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&/^2\d{2}$/.test(xhr.status)){
var val=xhr.responseText;
}
};
xhr.send(null);
# AJAX请求方式
# AJAX第一步
let xhr=new XMLHttpRequest
创建一个
AJAX
对象,IE6以下不支持;
# AJAX第二步:
TIP
xhr.open(method,url,async,username,userpass)
第二步代表发送前的基本信息配置(并没有发送请求)。open
方法中的参数详解如下:
method
:请求方式(以下方法都可以从服务器获取数据,也可以向服务器传递数据)GET
:一般用于从服务器获取数据(也可以向服务器发送数据)POST
:一般用于向服务器推送数据PUT
:用于给服务器上增加资源文件(上传图片)DELETE
:用于从服务器上删除资源文件HEAD
:用于只获取服务器的响应头信息
url
:请求的URL
地址(配置向哪一个服务器地址发送请求)async
:是否为异步(true代表异步,false代表同步,默认为true)- 用户名和密码:这两个参数一般不用,如果你请求的·地址所在的服务器设定了访问权限,则需要我们提供可通行的用户名和密码,才可以(一般服务器都是可以允许匿名访问的)
总结:
GET与POST区别:
- 1、大小问题:GET请求传递给服务器的内容大小存在限制而
POST
理论上没有限制。存在限制的原因是 浏览器对URL的长度存在限制。各浏览器都有自己的URL最大长度限制(谷歌:8KB,火狐:7KB,IE:2KB),超出的部分会被截取;而POST
请求一般都是基于 设置请求主体来实现的,理论上POST
通过请求主体传递是没有大小限制的; - 2、速度的问题:与
GET
请求相比,POST
请求消耗的资源会更多一些。从性能角度来看,以发送相同的数据计,GET
请求的速度最多可达到POST
请求的两倍 - 3、缓存的问题:
GET
请求会出现缓存(这个缓存不一定是304),会产生缓存是因为GET
请求是通过URL
问号传参来实现数据传递的(浏览器会根据每次请求时的URL地址与上次请求的地址是否相同,来判定是读取上次请求的缓存,还是再请求一次拿到最新数据);POST
是没有缓存的。如何解决GET
请求出现缓存:在URL
的末尾追加一个随机数;
$.ajax({
url:''+Math.random()
})
- 4、安全问题: 一般来说
GET
不安全,GET
请求是通过URL
传参把数据传递给服务器,用户名和密码将明文出现在URL
上,而黑客可通过URL
劫持获取到get
请求问号传参传递的内容。数据不太安全而POST
相对安全一些
# AJAX第三步
TIP
xhr.onreadystatechange=function(){}
此步骤作用:监听AJAX状
态改变,获取响应信息(获取响应头信息、获取响应主体信息)
xhr.onreadystatechange=function(){
if(xhr.readyState===4&&/^2\d{2}$/.test(xhr.status)){
var val=xhr.responseText;
}
};
# AJAX第四步:
xhr.send(null)
这一步才算发送请求:参数是请求主体中需要传递给服务器的内容
向服务器发送请求的任务,才算开始;
# xhr.readyState
AJAX状态码,代表当前AJAX处理的进度
可能的值如下:
- 0 :
UNSENT
当前的请求还没发送(未调用open
方法) - 1 :
OPENED URL
地址已经打开(已调用open
方法未调用send
方法) - 2 :
HEADERS_RECEIVED
当前AJAX
的请求已经发送,并且已经接收到服务器端返回的响应头信息了(已经调用send
方法,2的时候就已经可以拿到响应头信息了) - 3 :
LOADING
已经接收到部分响应数据 - 4 :
DONE
响应主体的内容已经成功返回到客户端
# xhr.status
HTTP网络状态码,描述了当前服务器返回信息的状态,
可能的值如下:
200 或者
^2\d{2}
: (200或以2开头的)都代表响应主体的内容已经返回成功以3开头的也算请求成功,只不过服务器端做了很多特殊的处理
- 301:永久重定向/永久转移(一般用于域名迁移)
- 302:临时重定向/临时转移(一般用于服务器的负载均衡,当服务器访问量过大,就把当前的请求临时交给其他服务器处理)
- 303:表示请求的资源路径发生改变,使用
GET
方法请求新url
。她与302
的功能一样,但是明确指出使用GET
方法请求新url
。 - 304:本次获取的内容是读取缓存中的数据(把一些不经常更新的文件或者内容缓存到浏览器中,下一次从缓存中获取,减轻服务器压力,也提高了页面加载速度)
- 307: 表示请求的资源路径临时发生改变,要求浏览器后续的请求应仍使用原本的
method
。可以确保请求方法和消息主体不会发生变化。 - 308: 表示请求的资源路径永久性的发生改变,要求浏览器后续的请求应仍使用原本的
method
。可以确保请求方法和消息主体不会发生变化。
以4开头的一般都是失败,而且客户端的问题偏大
- 400:客户端传递给服务器端的参数出现错误
- 401:无权限访问
- 404:要访问地址不存在
以5开头的一般都是失败,而且服务器端的问题偏大
- 500:未知的服务器错误
- 503:服务器已经超负荷
不同状态码对于SEO
的影响
- 301:当旧页面已经被收录了,使用301跳转到新的页面上,搜索引擎会把旧页面删除,替换成新的页面,并把旧页面的权重排名转移到新页面上,平稳过度。
- 302:和301的区别在于不会删除旧页面,但是会收录新的页面,不会将旧页面的权重排名转移到新的页面。
- 304:页面长时间出现大量304的状态码,会影响搜索引擎的信任度,会导致抓取频率和次数下降,页面内容收录速度表面,甚至不收录,网站快速更新变慢,甚至停止快照。网站的关键词排名下降,影响网站权重也下降。
# xhr.responseText
接收到的响应主体中的内容;
# AJAX属性
属性
readyState
:存储的是当前AJAX
的状态码response/responseText/responseXML
:都是用来接收服务器返回的响应主体中的内容,只是格式不一样responseText
:是最常用的,接收到的结果是字符串格式的(一般服务器返回的数据都是JSON格式字符串)responseXML
偶尔会用到,如果服务器返回的是XML
文档数据,需要用此属性接收
status
:服务器返回的HTTP
状态码statusText
:对返回状态码的描述timeout
:设置当前AJAX
请求的超时时间,表示请求在等待响应多少毫秒之后就终止。在给timeout
设置一个数值后,如果在规定的时间内浏览器还没有接收到响应,那么就会触发timeout
事件
# AJAX方法
方法
abort
:强制中断AJAX请求open
:打开一个URL地址send
:发送AJAX请求(参数是请求主体中传递给服务器的内容)getAllResponseHeaders
:获取全部的响应头信息(结果为字符串文本)getResponseHeader(key)
:获取指定属性名的响应头信息setRequestHeader(key,value)
:设置请求头信息(可以是自定义的请求头)overrideMimeType
:重写数据的MIME类型
# AJAX事件
事件
onabort
:AJAX
被中断触发此事件onreadyStateChange
:AJAX
状态发生改变触发此事件ontimeout
:请求超时后触发此事件
# JS中常用的编码解码方法
TIP
正常的编码解码(非加密)
- 1、
escape / unescape
:主要就是把中文汉字进行编码和解码(一般只有JS语言支持:常用于前端页面通信时候的中文汉字编码) - 2、
encodeURI / decodeURI
:基本上所有的编程语言都支持; - 3、
encodeURIComponent / decodeURIComponent
:使用对应的编码替换所有非字母数字字符。
encodeURI与encodeURIComponent的区别:
encodeURI()
编码后的结果是除了空格之外的其他字符都原封不动,只有空格被替换 。而 encodeURIComponent()
方法则会使用对应的编码替换所有非字母数字字符。
加密编码解码
- 1、可逆转加密(一般都是自己定规则)
- 2、不可逆转加密(基于
MD5
加密完成,为了安全一般都进行二次加密)
let str = 'http://www.baidu.com/?',
obj = {
name:'我在哪',
age:9,
url:'http://www.baidu.com/?lx=1'
};
//=>把OBJ中的每一项属性名和属性值拼接到URL的末尾(问号传参方式)
for(let key in obj){
str+=`${key}=${encodeURIComponent(obj[key])}&`;
//=>不能使用encodeURI必须使用encodeURIComponent,原因是encodeURI不能编码特殊的字符
}
console.log(str.replace(/&$/g,''));
//=>后期获取URL问号参数的时候,我们把获取的值在依次的解码即可
String.prototype.myQueryUrlParameter=function myQueryUrlParameter(){
let reg=/[?&]([^?&=]+)(?:=([^?&=]*))?/g,
obj={};
this.replace(reg,(...arg)=>{
let [,key,value]=arg;
obj[key]=decodeURIComponent(value);//=>此处获取的时候可以进行解码
});
return obj;
}
# AJAX中的同步异步
TIP
Ajax
中的同步:当AJAX
任务开始的时候,直到readyState
为4的时候任务才结束,此时才可以处理其他的事情;
Ajax
中的异步:当AJAX
任务开始的时候,不需要等到readyState
为4我依然可以继续做其他的任务,并且只有当其他的任务完成后,我们再看readyState
是否等于4,到4再做相关操作;
倒计时抢购时间差如何处理,在异步ajax
请求readyState
=2的时候拿到服务器时间,减少时间差。
# 倒计时抢购
let getSeverTime=function () {
let xhr=new XMLHttpRequest();
xhr.onreadystatechange=function () {
/*以2或3开头都算获取成功*/
if(!/^(2|3)\d{2}$/.test(xhr.status))return;
if(xhr.readyState===2){
/*只在第一次的时候获取服务器的时间,下次直接在其基础上+1就行*/
severTime=new Date(xhr.getResponseHeader("date")).getTime();
}
};
/*尽可能的减少时间差*/
/*只获取响应头信息即可,所以请求方式使用head即可,head请求中状态码没有3,因为不需要等待接收响应主体内容*/
xhr.open('head','json/banner.txt',true);
//只能使用异步,同步的时候无法在状态为2或3的时候做处理,而我们要获取响应头信息,在状态为2的时候就可以获取了,所以需要异步
xhr.send(null);
};
# jQuery中的AJAX
$.ajax({
url:'xxx.txt',
method:'get',
/*dataType只是我们预设获取结果的类型,无法影响服务器传递给我们的类型,只能拿到服务器的数据后,jQuery再进行转化*/
dataType:'json',
/*是否清除缓存*/
cache:true,
/*同步还是异步 false代表同步*/
async:true,
/*我们可以通过data属性把一些信息传递给服务器;get方式通过问号传参,post通过设置请求主体*/
/*data的值可以为:字符串、对象,如果是对象,JQ会把对象转化为xxx=xxx&xx=xx 这种字符串传递给服务器*/
data:null,
success:function (result) {
/*请求成功后(xhr.readyState为2或3开头)才会触发此函数*/
},
complete:function () {
/*不管请求是否成功都会触发此函数*/
}
})