逐渐深入地理解Ajax
Ajax的基本原理是:XMLHttpRequest对象(简称XHR对象),XHR为向服务器发送请求和解析服务器响应提供了流畅的接口。能够以异步方式从服务器获得更多信息。意味着用户不必刷新页面也能取得新数据,然后通过DOM将数据插入到页面中。 XMLHttpRequest对象方法如下: about():停止当前的请求; open(“method”,”URL”,[asyncFlag]): 等常见的方法; XHR的基本用法: 在使用XHR对象时,要调用的第一个方法是open()方法,它有三个参数,第一个参数是:需要发送请求的类型(get或者post),第二个参数是请求的url,第三个参数是请求的布尔值(true是异步,false是同步); xhr.open(‘get’,'http://127.0.0.1/ajax/ajax.php’,false); 如上代码会启动一个get请求ajax.php,但是请注意:open方法并不会真正发请求,而只是启动一个请求以备发送; 要发送真正请求必须使用send()方法;如下: xhr.send(null); send的方法接收一个参数,需要请求发送的数据,如果请求不需要发送数据,需要传送一个null,因为对于有些浏览器这是必须的;上面第三个参数传的是false,是同步请求,服务器接收到响应后再继续执行后面的代码,响应后的数据会自动填充XHR对象的属性,XHR有以下属性: responseText: 作为响应主体被返回的文本。 responseXML: 如果响应的内容是”text/xml” 或 “application/xml”,这个属性将保存包含响应数据的XML DOM文档; status: 响应http状态; statusText: http状态说明; 在接收到响应后,第一步是检查status状态,如果状态时200,说明已经成功返回,此时responseText属性已经就绪;如果状态是304,说明资源未被修改,可以直接使用浏览器缓存的版本,当然,响应是有效的;如下ajax请求代码;
ajax.php代码如下:
发ajax请求后,在控制台中打印如下:
说明已经请求成功; 上面的demo代码是同步请求,但是有时候我们需要发送异步请求,才能让javascript后续代码继续执行而不会堵塞,此时,我们可以检测XHR对象的readyState属性,该属性表示请求/响应当前活动阶段;这个属性取值如下: 0:未初始化。尚未调用open()方法; 1:启动。已经调用open()方法,但未调用send()方法; 2:发送。已经调用send()方法,但尚未接收到响应; 3:接收。已经接收到部分数据; 4:完成。已经接收到全部响应数据,而且可以在客户端使用了; readyState属性值由一个值变为另一个值,就会触发一次readystatechange事件。可以利用这个事件检测每次状态变化后的readyState值,但是必须在调用open()方法之前指定onreadystatechange事件;如下代码:
19
20
21
22
23
24
|
(window.XMLHttpRequest){
{
}
xhr;
}
xhr = createXHR();
xhr.onreadystatechange =
(){
(xhr.readyState == 4) {
((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
console.log(xhr.responseText);
{
console.log(xhr.status);
}
}
}
);
);
|
如上代码,在处理onreadystatechange事件时使用了xhr对象,没有使用this对象,原因是onreadystatechange事件处理程序的作用域的问题;如果使用this对象,在有的浏览器下会执行失败,或者导致错误发生;
理解Http头部信息
每个http请求和响应都会带有响应的头部信息,xhr对象也提供了操作这两种头部(请求头部和响应头部的)信息的方法;
默认情况下,在发送XHR请求的同时,还会发送下列头部信息:
Accept: 浏览器能够处理的内容类型;
Accept-Charset: 浏览器能够显示的字符集;
Accept-Encoding: 浏览器能够处理的压缩编码;
Accept-Language: 浏览器当前设置的语言;
Connection: 浏览器与服务器之间连接的类型;
Cookie:当前页面设置的cookie;
Host:发出请求页面所在的域;
Referer:发出请求的页面url。
User-Agent: 浏览器的用户代理字符串。
如下ajax.php请求所示:
我们还可以使用setRequestHeader()方法可以设置自定义的请求头部信息,这个方法接收2个参数:头部字段的名称和头部字段的值;要成功发送请求头部信息,必须在调用open()方法之后且调用send()方法之前调用setRequestHeader();如下demo所示:
xhr.setRequestHeader(
"myHeader"
"myValue"
);
截图如下:
调用getAllResponseHeaders()方法则可以取得一个包含所有头部信息的长字符串,如上代码中在onreadystatechange事件中添加getAllResponseHeaders()方法:
9
(xhr.readyState == 4) {
((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
myHeader = xhr.getAllResponseHeaders();;
console.log(myHeader);
{
console.log(xhr.status);
}
打印如下:
理解GET请求
在ajax中,有常见的get请求或者post请求,使用get请求时,我们是把参数的名-值对经过encodeURIComponent()进行编码,然后放到URL的末尾,所有名值对必须由和好(&)分割;如下代码:
1
true
下面我们可以封装一个方法可以辅助向现有的URL的末尾添加查询字符串参数;
addURLParam(url,name,value) {
url += url.indexOf(
"?"
) == -1 ?
:
"&"
;
url += encodeURIComponent(name) +
"="
+ encodeURIComponent(value);
url;
如下代码测试:
24
25
26
27
28
29
30
31
32
33
XMLHttpRequest();
);
}
xhr;
}
xhr = createXHR();
(){
(xhr.readyState == 4) {
((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
myHeader = xhr.getAllResponseHeaders();;
console.log(myHeader);
}
url =
"http://127.0.0.1/ajax/ajax.php"
;
url = addURLParam(url,monospace!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.1em!important; outline:0px!important; overflow:visible!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; min-height:auto!important; color:blue!important">"name1"
"value1"
);
"name2"
"value2"
);
);
);
);
;
+ encodeURIComponent(value);
url;
如下截图所示:
理解POST请求:
Post请求时作为请求的主体提交,post请求的主体可以是非常多的数据,而且格式不限;在open方法的第一个参数传入post,就可以初始化post请求,如下:xhr.open(‘post’,”http://127.0.0.1/ajax/ajax.php”,true);
接下来我们需要使用send()方法来发送数据,传入的参数可以是任何的字符串或者form表单序列化之后的数据;比如我们现在可以使用xhr来模仿表单提交数据,首先我们需要将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交的内容类型,其次以适当的格式创建一个字符串,比如form表单序列化数据,然后通过xhr发送到服务器端,
如下HTML代码:
4
"form"
>
<input name=
"user-name"
value=
"aaa"
/>
"user-email"
"233"
/>
</form>
JS代码如下:
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
// 序列化的代码
serialize(form) {
arrs = [],
field =
len,
j,
optLen,
option,
optValue;
for
(i = 0,len = form.elements.length; i < len; i++) {
field = form.elements[i];
switch
(field.type) {
case
"select-one"
:
"select-multiple"
:
(field.name.length) {
(j = 0,optLen = field.options.length; j < optLen; j++) {
option = field.options[j];
(option.selected) {
optValue =
''
;
(option.hasAttribute) {
optValue = option.hasAttribute(
"value"
) ? option.value : option.text;
{
optValue = option.attributes[
].specified ? option.value : option.text;
}
arrs.push(encodeURIComponent(field.name) +
+encodeURIComponent(optValue));
}
}
}
break
case
undefined:
//字段集
"file"
:
// 文件输入
"submit"
// 提交按钮
"reset"
// 重置按钮
"button"
// 自定义按钮
;
"radio"
// 单选框
"checkbox"
// 复选框
(!field.checked) {
;
}
/* 执行默认动作 */
default
:
// 不包含没有名字的表单字段
(field.name.length) {
+encodeURIComponent(field.value));
}
}
}
arrs.join(
);
}
;
'post'
);
"Content-Type"
"application/x-www-form-urlencoded"
);
form = document.getElementById(
);
xhr.send(serialize(form));
|
之后我们可以看到form表单序列化之后传过去的数据如下:
XMLHttpRequest 2级
XMLHttpRequest 1级只是把已有的xhr对象的实现细节描述出来了,而XMLHttpRequest 2级是在原来的基础上增加了一些规范,但所有的浏览器只是实现了他规定的部分内容;如下几个:
理解FormData
现在web应用中频繁使用的一项功能是form表单序列化,XMLHttpRequest 2级定义了FormData类型,使用FormData获取数据与表单序列化数据一样,但是更简洁方便;
支持FormData浏览器有:firefox4+,safari5+,chrome和Android3+版的webkit.
比如我现在提交form表单数据如下demo:
HTML代码:
);
FormData(form));