Ajax 即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。
要学一门技术,最基本名字是要读正确的,美式发音音标:[ˈeˌdʒæks] 。对于ajax的这个名字,究其历史原因,当时Ajax技术使用于JavaScript之上,进行的是XML格式数据的传输,通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新,这样新颖的技术在当时起名:Asynchronous Javascript And XML。但现在XML逐渐被淘汰不在多见了,但ajax强大的异步加载数据功能被保留,所以现在最多做的是利用ajax与json搭配进行前后端的数据交互,理解这一点我们在下面看到带有xml的方法名或者对象名也就不觉得奇怪了。下面我们就直击主题看一下ajax如何在前端实现的。
仔细看下面注释,逐句解释一下。
var xhr = new XMLHttpRequest();//名字带有‘xml’的对象
//new 一个请求代理对象。
xhr.open('GET','time.php?id=1');
//建立一个与服务端特定端口的连接(服务端端口一般是80端口),以get方式传输数据
xhr.send(null);
//发送一个请求,请求体内为null(因为是GET请求,这里不放入数据,所以数据会以?id=1的方式传输数据,当为post请求时这里会放入数据。)
xhr.addEventListener('readystatechange',function() {
//注册事件,readystatechange该事件用于监控ajax每个状态的转换,只要转换则就触发该事件。
if(this.readyState !== 4)return;
//判断xhr.readyState(ajax状态码)是否为4,不为4则说明没有拿到返回数据
console.log(this.responseText);
//返回的数据
});
ajax状态码,获取方式
var xhr = new XMLHttpRequest();
xhr.readyState
xhr.readyState在整个ajax操作流程中可以出现5个值,而用readystatechange
事件只能检测到4个值
有些文章写到
readystatechange
事件能检测到三个值,还是有点坑的,其实可以到四个,只需要提前注册一下该事件我们就可以看到。如:
var xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange',function() {
console.log(this.readyState);//四个值:1,2,3,4
});
xhr.open('GET','time.php');
xhr.send(null);
var xhr = new XMLHttpRequest()
console.log(xhr.readyState)
// => 0
// 初始化 请求代理对象
xhr.open('GET', 'time.php')
console.log(xhr.readyState)
// => 1
// open 方法已经调用,建立一个与服务端特定端口的连接
xhr.send()
xhr.addEventListener('readystatechange', function () {
switch (this.readyState) {
case 2:
// => 2
// 发送send请求,且已经接受到了响应报文的响应头
// 可以拿到头
// console.log(this.getAllResponseHeaders())
console.log(this.getResponseHeader('server'))
// 但是还没有拿到体
console.log(this.responseText)
break
case 3:
// => 3
// 正在下载响应报文的响应体,有可能响应体为空,也有可能不完整
// 在这里处理响应体不保险(不可靠)
console.log(this.responseText)
break
case 4:
// => 4
// 一切 OK (整个响应报文已经完整下载下来了)
console.log(this.responseText)
break
}
})
上面了解了这么多我们,ajax实现基本流程与get请求已经了解了一个大概,下面我们进行一次post请求,其实与get请求大同小异,唯一不同也许需要设置一下请求头的content-type。
var xhr = (new XMLHttpRequest());
xhr.open('POST','time.php');
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//设置请求头的Content-Type为application/x-www-form-urlencoded(简单理解为键值对形式)
//除此外Content-Type还可以设置为:application/json(json格式数据),application/xml(xml格式数据),multipart/form-adta(文件)
xhr.send('key1=value1&key2=value2');//需要发送的数据
xhr.addEventListener('readystatechange',function() {
if(this.readyState !== 4)return;
console.log(this.responseText);
});
var xhr = (new XMLHttpRequest());
xhr.open('GET','time.php');
//建里连接
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//设置头部信息
xhr.send('key1=value1&key2=value2');
//发送请求
xhr.addEventListener('readystatechange',function() {
if(this.readyState !== 4)return;
console.log(this.status);//响应状态码,如:200表示成功
console.log(this.statusText);//响应状态文字描述,如:状态码为200,这里是ok。
console.log(this.getResponseHeader('Content-Type'));//查看响应报文的Content-Type,数据格式信息
console.log(this.responseText);//查看响应体信息,即返回的数据。
});
同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式。用户填写所有信息后,提交给服务器,等待服务器的回应(检验数据),是一次性的。信息错误又要重新填写!
异步是指:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式。当用户填写完一条信息后,该信息会自动向服务器提交,然后服务器响应客户端,在此过程中,用户依然在填写表格的信息,即向服务器请求多次,节省了用户的时间,提高了用户的体验。
原文连接
设置方式:在xhr.open()方法内传入第三个参数,默认为true(异步),传入false则设置为同步方式。
var xhr = new XMLHttpRequest();
xhr.open('GET','time.php',false);
注意一点的是,在使用同步方式时,浏览器会提示:
也就是说ajax的同步方式是Deprecation的,不赞成的。所以尽量用异步方式。
服务端:
header("Content-Type: application/json");
//设置响应报文Content-Type
$timeDate = array(//需要给前端的数据
'time' => date('Y-m-d H:i:s',time()),//当前时间
'history' => '1990-01-01 00:00:00'//一个历史时间
);
if(empty($_GET['key'])){
//没有请求值,返回全部数据
$json = json_encode($timeDate);
}else{
//有请求值,返回请求值对应数据
$json = json_encode($timeDate[$_GET['key']]);
}
echo $json;
前端
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>检测事件title>
head>
<body>
<div>div>
<script>
var divEle = document.getElementsByTagName('div')[0];
var xhr = new XMLHttpRequest();
xhr.open('GET', 'time.php');
xhr.send();
xhr.addEventListener('readystatechange', function() {
if (this.readyState !== 4) return;
if (this.status !== 200) {
console.log("错误" + this.status);
return
}
console.log(this.responseText);
var timeData = JSON.parse(this.responseText);
divEle.innerText = timeData.time;
});
script>
body>
html>
1,利用console.time()与console.timeEnd()测试代码执行时间:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'time.php',true);
console.time('GET_t');
xhr.send();
console.timeEnd('GET_t');
var xhr2 = new XMLHttpRequest();
xhr2.open('GET', 'time.php',false);
console.time('GET_f');
xhr2.send();
console.timeEnd('GET_f');
执行结果:
由此我们也可以看出同步方式与异步方式执行时间上的差别,这个差别在实际传输中还会放大。
2,用onload事件代替onreadystatechange事件
var xhr3 = new XMLHttpRequest();
xhr3.open('GET', 'time.php',true);
xhr3.send();
xhr3.onload = function () {
if(this.readyState!==4)return;
console.log(this.responseText);
}
3,获取数据前设置数据响应类型
xhr.responseType = 'json';//
设置响应数据的类型为json,设置后获取的数据就是json格式了,无需JSON.parse进行数据转换。
注:但是存在兼容问题,IE10以上版本才可以使用
var xhr4 = new XMLHttpRequest();
xhr4.open('GET', 'time.php',true);
xhr4.send();
xhr4.responseType = 'json';
xhr4.onload = function () {
if(this.readyState!==4)return;
console.log(this);
}
var xhr = window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject( "Microsoft.XMLHTTP ");