Ajax

普通的表单提交方式是同步的,会刷新整个页面。

Ajax概念

AJAX = 异步 JavaScript 和 XML。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。

Ajax实例

1.创建异步对象XMLHttpRequest对象

XMLHttpRequest对象

所有现代浏览器均支持 XMLHttpRequest对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
创建 XMLHttpRequest对象的语法:

1
let xmlhttp=new XMLHttpRequest();

2.设置请求方式和请求地址

如需将请求发送到服务器,我们使用XMLHttpRequest对象的open()send()方法:

1
2
xmlhttp.open("GET","test1.txt",true);
xmlhttp.send();
方法 描述
open(method,url,async) 规定请求的类型、URL 以及是否异步处理请求。
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)

GET请求

1
xmlhttp.open("GET","demo_get.asp",true);

在上面的例子中,可能得到的是缓存的结果。在IE浏览器中,如果通过Ajax发送GET请求,那么IE浏览器认为同一个URL只有一个结果(不能实时拿到请求文件当中变化的数据),所以必须保证每一次请求的地址不一样。解决方法:向 URL 添加一个唯一的 ID、随机数或者时间戳(为了防止URL后每次添加的数据不一样,有效的避免缓存)。

1
xmlhttp.open("GET","demo_get.asp?t=" + Math.random(),true);

如果您希望通过 GET 方法发送信息,请向 URL 添加信息(查询字符串):

1
xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true);

POST请求

1
xmlhttp.open("POST","demo_post.asp",true);

如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader()来添加 HTTP 头。然后在 send()方法中规定您希望发送的数据:

1
2
3
xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");
方法 描述
setRequestHeader(header,value) 向请求添加 HTTP 头。
header: 规定头的名称
value: 规定头的值

3、发送请求

方法 描述
send(string) 将请求发送到服务器。
string:仅用于 POST 请求
1
xmlhttp.send();

4、监听状态的变化

属性 描述
onreadystatechange 存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数
readyState 1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
status 200: “OK”
404: 未找到页面

Http状态码

HTTP状态码用于表示客户端请求的处理结果。状态码的第一个数字定义了响应的类别,而后面的两位数字没有具体规定,它们的解释在不同的类别中可能有不同的含义。具体到状态码的范围,2xx 表示成功的响应。

具体说,HTTP状态码中,状态码的第一个数字定义了响应的类别,例如:

  • 1xx : 表示请求已被接受,继续处理。
  • 2xx : 表示请求已成功被服务器接收、理解、并接受。
  • 3xx : 表示需要客户端采取进一步的操作才能完成请求。
  • **4xx ** 表示客户端似乎有错误,包括诸如请求中的语法错误或无法完成请求等情况。
  • 5xx : 表示服务器无法完成明显有效的请求。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
xmlhttp.onreadystatechange = function (ev) {
/*
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
*/
if(xmlhttp.readyState === 4){
// 判断是否请求成功
if(xmlhttp.status >= 200 && xmlhttp.status < 300 ||
xmlhttp.status === 304){
console.log("没有接收到服务器返回的数据");
}else{
console.log("没有接收到服务器返回的数据");
}

}
}

5.处理返回的结果

请求成功后,便可处理返回结果

1
2
3
4
5
6
7
8
9
10
11
12
13
xmlhttp.onreadystatechange = function (ev) {
if(xmlhttp.readyState === 4){
if(xmlhttp.status >= 200 && xmlhttp.status < 300 ||
xmlhttp.status === 304){
//处理返回的结果
console.log("没有接收到服务器返回的数据");
}else{
console.log("没有接收到服务器返回的数据");
}

}
}

提问

1.发送ajax请求的5个步骤

2.异步对象onreadystatechange的作用是什么

3.异步对象redyState属性保存的是什么

4.异步对象status属性保存的是什么

封装Ajax的GET请求

每次想利用Ajax发送请求时都要这五步代码,而且代码一样,所以封装好,每次调用这个方法即可,将不确定的参数让调用者传进来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
function ajax(url,obj,timeout,success,error){
// 将传进来的对象转换为字符串
var str = objConversion(obj);// key=value&key=value;
var xmlhttp,timer;
// 判断浏览器是否兼容
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// 为了得到服务器最新的数据,在url后加上时间戳
xmlhttp.open("GET",url+"?"+str,true);
xmlhttp.send();
xmlhttp.onreadystatechange = function (ev) {
if(xmlhttp.readyState === 4){
clearInterval(timer);
if(xmlhttp.status >= 200 && xmlhttp.status < 300 ||
xmlhttp.status === 304){
// alert("请求成功");
success(xmlhttp);
}else{
// alert("请求失败");
error(xmlhttp);
}
}
}
// 判断外界是否传入了超时时间
if(timeout){
timer = setInterval(function () {
console.log("中断请求");
xmlhttp.abort();
clearInterval(timer);
}, timeout);
}
}
function objConversion(obj) {
/*对象格式
{
"userName":"lnj",
"userPwd":"123456",
"t":"3712i9471329876498132"
}
*/
obj = obj || {}; // 如果没有传参, 为了添加随机因子,必须自己创建一个对象
// 创建时间戳
obj.t = new Date().getTime();
var res = [];
for(var key in obj){
// 在URL中是不可以出现中文的, 如果出现了中文需要转码
// 可以调用encodeURIComponent方法
// URL中只可以出现字母/数字/下划线/ASCII码
res.push(encodeURIComponent(key)+"="+encodeURIComponent(obj[key])); // [userName=lnj, userPwd=123456];
}
return res.join("&"); // userName=lnj&userPwd=123456
}

//调用
ajax("04-ajax-get.php", //url
{"userName":"lnj", //obj
"userPwd":"123456"},
3000, //timeout
function (xhr) {
alert(xhr.responseText); //success
},
function (xhr) {
alert("请求失败"); //error
}
);

提问

1.当前封装的Ajax如果不传递参数会不会报错?

2.如何解决不传递参数报错的问题?

3.为什么要对请求超时进行处理?

4.如何将中文转换成符合URL格式的字符串?

封装Ajax的Post请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
function ajax(url,obj,timeout,success,error){
// 将传进来的对象转换为字符串
var str = objConversion(obj);// key=value&key=value;
var xmlhttp;
// 判断浏览器是否兼容
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// 为了得到服务器最新的数据,在url后加上时间戳
xmlhttp.open("POST",url,true);
//因为不是像GET一样在url后面添加,而是在请求头中发送数据,所以要设置请求头,注意只能在open和send之间
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(str);
xmlhttp.onreadystatechange = function (ev) {
if(xmlhttp.readyState === 4){
if(xmlhttp.status >= 200 && xmlhttp.status < 300 ||
xmlhttp.status === 304){
// alert("请求成功");
success(xmlhttp);
}else{
// alert("请求失败");
error(xmlhttp);
}
}
}
}
function objConversion(obj) {
/*对象格式
{
"userName":"lnj",
"userPwd":"123456",
"t":"3712i9471329876498132"
}
*/
obj = obj || {}; // 如果没有传参, 为了添加随机因子,必须自己创建一个对象
// 创建时间戳
obj.t = new Date().getTime();
var res = [];
for(var key in obj){
// 在URL中是不可以出现中文的, 如果出现了中文需要转码
// 可以调用encodeURIComponent方法
// URL中只可以出现字母/数字/下划线/ASCII码
res.push(encodeURIComponent(key)+"="+encodeURIComponent(obj[key])); // [userName=lnj, userPwd=123456];
}
return res.join("&"); // userName=lnj&userPwd=123456
}


}
function objConversion(obj) {
/*对象格式
{
"userName":"lnj",
"userPwd":"123456",
"t":"3712i9471329876498132"
}
*/
obj = obj || {}; // 如果没有传参, 为了添加随机因子,必须自己创建一个对象
// 创建时间戳
obj.t = new Date().getTime();
var res = [];
for(var key in obj){
// 在URL中是不可以出现中文的, 如果出现了中文需要转码
// 可以调用encodeURIComponent方法
// URL中只可以出现字母/数字/下划线/ASCII码
res.push(encodeURIComponent(key)+"="+encodeURIComponent(obj[key])); // [userName=lnj, userPwd=123456];
}
return res.join("&"); // userName=lnj&userPwd=123456
}

//调用
ajax("POST", "08-ajax-post.php", //url
{"userName":"lnj", //obj
"userPwd":"321"},
3000, //timeout
function (xhr) {
alert(xhr.responseText); //success
},
function (xhr) {
alert("请求失败"); //error
}
);

提问

1.Ajax发送POST请求,如何传递参数

2.setRequestHeader方法必须写到哪个位置

3.怎么实现写一个Ajax函数,能处理GET和POST请求

添加一个type参数,在设置请求方式和请求地址那里加一个判断

优化封装的Ajax

type.toLowerCase

参数传递顺序打乱怎么办(改成传递的参数是一个对象,从对象取属性,就不用担心顺序了)

JSON

服务器返回数据给前端,一般就两种方式,一种是XML,一种是JSON
JSON是js对象的字符串表示法,它使用文本表示一个js对象的信息,本质是一个字符串

1
2
let obj={a:'hello',b:'world'}//这是一个js对象,注意键名也是可以使用字符串包裹的
let json='{"a":"hello","b":"world"}'//这是一个JSON字符串,本质是一个字符串

对象 –> JSON

1
let json=JSON.stringify({a:'hello',b:'world'})//结果是'{"a":"hello","b":"world"}'

JSON –> 对象

1
2
3
let obj=JSON.parse('{"a":"hello","b":"world"}')
//只能转换标准的json字符串,键和值都用双引号包裹
//如果服务器返回的是非标准的字符串,用let obj=eval("("+str+")"),它既可以转换标准的字符串为对象还可以转换非标准的json字符串,还可以用它转换json字符串组成的数组,可以不加圆括号。

IE8以下的浏览器不支持使用parse,如果想要在IE8以下的浏览器使用,需要用上一个框架json2.js

在github中把json2.js文件下载到项目中然后引入,即在页面中添加json2.js的引用,详细使用请看json2.js使用参考

1
<script type="text/javascript" src="json2.js所在目录"></script>