关于AJAX
AJAX是asynchronous javascript + XML的简写,它是一种能够向服务器请求数据而无需刷新页面的技术。AJAX能够提供更加友好的用户体验,彻底改变了传统的'点击、等待'的交互模式。
AJAX技术的核心是XMLHttpRequest对象。XHR对象中的名字虽然有XML,但是AJAX通信与数据格式无关。
XMLHttpRequest对象
IE7+和标准浏览器都支持XMLHttpReuqest对象。在IE6-中是通过ActiveXObject对象以插件的形式实现的。
1 function fnGetXHR(){ 2 if(window.XMLHttpRequest){ 3 return new XMLHttpRequest; 4 }else{ // IE6- 5 return new window.ActiveXObject("Microsoft.XMLHTTP"); 6 } 7 }
XHR的用法
1、调用open方法启动一个AJAX请求以备发送。
open方法:open(请求方式,URL地址,是否异步发送请求的布尔值);
2、调用send方法向服务器发送请求。
send(向请求主体发送的数据 || null);如果不需要向请求主体发送数据,该值最好设置为null,因为这个参数对有的浏览器是必须的。
3、监控readyStateChange事件,根据readyState属性来处理服务器端的响应(如果不是异步的可以直接在send方法后处理服务器端的响应)。
XHR对象服务端响应的相关属性:
①、responseText:响应主体
②、responseXML:如果响应内容的类型是text/xml或application/xml该属性保存响应的xml dom文档
③、status:响应的HTTP状态码 其中(status >= 200 && status < 300 || status === 304)是响应成功的取值
④、statusText:HTTP状态的说明(有兼容性)
XHR对象的readyState属性:
①、0(未初始化):open方法还没调用
②、1(启动):open方法已经调用,send方法未调用
③、2(发送):send方法已经调用,还没收到服务器端的响应
④、3(接受):接受到部分服务器端的响应
⑤、4(完成):接收到全部服务器端的响应,这些响应在客户端可以使用了
同步请求:如果请求是同步的,send之后的代码会等待服务器响应之后才能执行。收到响应后响应数据会自动填充到XHR对象服务器端响应的相关属性。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', false); 3 xhr.send(null); 4 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 5 console.log(xhr.responseText); 6 }
异步请求:如果请求是异步的,需要在readyStateChange事件中来检测readyState属性的值,当readyState等于4时响应数据就会自动填充到XHR对象服务器端响应的相关属性。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', true); 3 xhr.send(null); 4 xhr.onreadystatechange = function(){ 5 if(xhr.readyState == 4){ 6 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 7 console.log(xhr.responseText); 8 } 9 } 10 }
异步请求在接受到响应之前还可以通过abort方法来取消。同步请求不能取消,另外abort方法必须在send方法之后调用否则会报错。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', true); 3 xhr.onreadystatechange = function(){ 4 if(xhr.readyState == 4){ 5 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 6 console.log(xhr.responseText); // 不会执行 7 } 8 } 9 } 10 xhr.send(null); 11 xhr.abort();
NOTE:同步请求去监控readystatechange事件时必须放在send方法之前。如果放在send方法之后readystatechange绑定的事件处理函数已经在事件触发以后了。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', false); 3 // xhr.send(); // 对于同步请求send放在这儿的话事件的绑定已经在事件触发后,没有作用 4 xhr.onreadystatechange = function(){ 5 if(xhr.readyState == 4){ 6 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 7 console.log(xhr.responseText); 8 } 9 } 10 } 11 xhr.send(null);
HTTP头部信息
每个HTTP请求和响应都会带有相应的头部信息。
默认情况下,XHR请求会带有下面的头部信息:
Accept:浏览器能处理的内容类型(*/*)
Accept-Encoding:浏览器能处理的压缩编码(gzip,deflate,sdch)
Accept-Language:浏览器当前设置的语言(zh-CN,zh;q=0.8,en;q=0.6)
Connection:浏览器与服务器之间的连接类型(keep-alive)
Cookie:当前页面设置的任何cookie
Host:发出请求的页面所在的域(localhost:63342)
Referer:发出请求的页面的URI(http://localhost:63342/www/ajax/test.html)
User-Agent:浏览器的用户代理字符串(Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36)
......
使用XHR的setRequestHeader可以设置自定义的请求头部信息,但是必须在send方法之前使用才有效。建议不要修改浏览器默认的请求头部信息,可能会报错。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', true); 3 xhr.onreadystatechange = function(){ 4 if(xhr.readyState == 4){ 5 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 6 console.log(xhr.responseText); 7 } 8 } 9 } 10 xhr.setRequestHeader('Auth', 'hum'); // 添加成功 11 //xhr.setRequestHeader('User-Agent', 'hum'); // 尝试修改默认的会报错误 12 xhr.send(null); 13 //xhr.setRequestHeader('Auth', 'hum'); // send方法之后使用报错
使用XHR的getResponseHeader可以获取相应的响应头部信息。也可以通过getAllResponseHeaders方法来获取所有的响应头部信息。
1 var xhr = fnGetXHR(); 2 xhr.open('get', 'data.txt', true); 3 xhr.onreadystatechange = function(){ 4 if(xhr.readyState == 4){ 5 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 6 console.log(xhr.getResponseHeader('Content-Length')); 7 console.log(xhr.getAllResponseHeaders()); // 不能用JSON.parse方法解析 8 } 9 } 10 } 11 xhr.send(null);
AJAX请求类型
1、get请求
GET是最常用的请求类型,常用于向服务器查询某些信息。可以将查询字符串放在URL的末尾,发送给服务器。
使用GET请求的查询字符串的每个名称和值都必须通过encodeURIComponent进行编码,然后才能放在URL末尾,并且所有的键值对都必须用&符号分隔。
1 xhr.open('get', 'data.php?name1=value1&name2=value2'); // 查询字符串 2 // 获取URLParam的辅助方法 3 function fnGetURLParam(data){ 4 var urlParam = []; 5 for(var key in data){ 6 urlParam.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key])); 7 } 8 return urlParam.join('&'); 9 } 10 console.log(fnGetURLParam({name: 'hum', age: 20})); // name=hum&age=20
2、post请求
POST请求会把数据作为请求的主体提交。POST请求的主题可以包含比较多的数据,数据格式可以多样。POST请求的数据放在send方法中。
默认情况下,服务器对AJAX的POST请求和web form的请求并不一样,因此服务器端不能像web form一样的方式来获取数据,不过我们可以通过XHR来模仿表单提交:
将Content-type头部信息设置为application/x-www-form-urlencoded,也就是web form向服务器端发送数据的类型。这样服务器可以像获取表单数据一样获取AJAX post方式提交的数据。
1 var xhr = fnGetXHR(); 2 xhr.open('post', 'data.php', true); 3 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 4 xhr.onreadystatechange = function(){ 5 if(xhr.readyState == 4){ 6 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ 7 console.log(xhr.responseText); 8 } 9 } 10 } 11 xhr.send(fnGetURLParam({name: 'hum', age: 20}));