什么是Ajax?

Ajax全称为”Asynchronous JavaScript and XML”(异步的JavaScript和XML),Ajax的核心是XMLHttpRequest对象,它可以和服务器进行通信,发送异步请求,接收服务器发来的数据。其中数据的格式可以包括JSON, XML, HTML和文本等格式。

Ajax的优势:

  1. 不需插件支持
    Ajax不需要任何浏览器插件,就可以被浏览器所支持。

  2. 优秀的用户体验
    能在不刷新整个页面的前提下更新数据。

  3. 提高Web程序的性能
    传统模式中,数据的提交是通过表单来实现的,而数据获取是靠全页面刷新来重新获取整个页面内容。Ajax只是通过XMLHttpRequest对象向服务器端提交希望提交的数据。

  4. 减轻服务器和宽带的负担
    Ajax的工作原理相当于在用户和服务器之间加了一个中间层,使用户操作与服务器响应异步化。它在客户端创建Ajax引擎,把传统方式下的一些服务器负担的工作转移到客户端。

Ajax的不足

  1. 浏览器对XMLHttpRequest对象的支持度不足
  2. 对搜索引擎的支持的不足
  3. 开发和调试工具的缺乏

核心:XMLHttpRequest

解释:

XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequest 在 AJAX 中被大量使用。

历史:

XMLHttpRequest 最初由微软设计,随后被 Mozilla、Apple 和 Google采纳。如今,该对象已经被 W3C组织标准化。 通过它,你可以很容易的取回一个 URL 上的资源数据。尽管名字里有 XML,但 XMLHttpRequest 可以取回所有类型的数据资源,并不局限于 XML。而且除了 HTTP ,它还支持 file 和 ftp 协议。

构造函数:

1
XMLHttpRequest()

常用属性:

  1. onreadystatechange
    一个方法(回调函数),当readyState属性改变时会调用它。

  2. readyState
    一个整型数字,代表请求的5种状态。
    值  状态                 描述
    0  UNSENT(未打开)          open()方法还未被调用
    1  OPENED(未发送)          open()方法已被调用
    2  HEADERS_RECEIVED(以获取响应头) send()方法已被调用,响应头和响应状态已经返回
    3  LOADING(正在下载响应体)     响应体下载中;responseText中已经获取了部分数据
    4  DONE(请求完成)          整个请求过程已经完毕

  3. response
    响应实体,多种类型,失败为null。

  4. responseText
    响应实体为文本,失败为null。

  5. responseType
    期待响应的类型。

  6. responseXML
    响应的类型是Document。

  7. status
    响应的状态码。

  8. statusText
    响应的状态信息。

  9. timeout
    代表着一个请求在被自动终止前所消耗的毫秒数。

常用方法:

  1. abort()
    请求被发送后(send方法调用后),终止请求。

  2. open(method, url, async, user, password)
    初始化请求。(method必须为大写)

  3. send(body)
    发送请求,请求为异步的话方法会立刻返回,请求为同步的话方法会等到响应到达时返回。body为发送内容。

  4. setRequestHeader(header, value)
    设置请求的header,使用原生ajax的时候,发送请求需要设置的包括Access-Control-Allow-Origin,Content-Type头信息。

事件接口:

  1. loadstart
    Progress has begun.

  2. progress
    In progress.

  3. error
    Progression failed.

  4. abort
    Progression is terminated.

  5. timeout
    Progression is terminated due to preset time expiring.

  6. load
    Progression is successful.

  7. loadend
    Progress has stopped.

使用XMLHttpRequest对象发送Ajax请求的基本步骤

  1. 创建XMLHttpRequest对象。
  2. 告诉XMLHttpRequest对象由哪一个函数处理响应。
  3. 使用XMLHttpRequest对象的open方法,设置请求类型,请求地址以及是否采用异步。
  4. 使用XMLHttpRequest对象的send方法,方法的参数是任何想要发送的内容。如果是GET请求,那么send方法的参数为null;如果是POST请求,那么需要在发送请求前设置请求的MIME类型。

简单例子

这个Ajax例子是一个输入框,输入省份的首字母,在输入框下面会显示省份的所有城市。
这里采用了mock的方式生成城市的数据,为了以后扩展扩展这个应用,我们使用模块化的方式编写。

项目目录:
dist
    bundle.js
mock
    data.js
src
    search.js
index.html
package.json
webpack.config.js

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ajax-Search</title>
<style>
.container {
overflow: hidden;
width: 100%;
}
</style>
</head>
<body>
<div class="container" id="container">
<input type="search" id="province" />
<div id="city-container"></div>
</div>
</body>
<script src="./dist/bundle.js"></script>
</html>

data.js

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
var Mock = require('mockjs');
var HLJ = Mock.mock(/hlj\.json/, {
'city': {
'110000': '哈尔滨市',
'110001': '齐齐哈尔市'
}
});
var LN = Mock.mock(/ln\.json/, {
'city': {
'220000': '沈阳市',
'220001': '大连市'
}
});
var JL = Mock.mock(/jl\.json/, {
'city': {
'330000': '长春市',
'330001': '吉林市'
}
});
var ZJ = Mock.mock(/zj\.json/, {
'city': {
'440000': '杭州市',
'440001': '舟山市'
}
});
var GZ = Mock.mock(/gz\.json/, {
'city': {
'550000': '广州市',
'550001': '惠州市'
}
});
module.exports = {
HLJ,
LN,
JL,
ZJ,
GZ
};

search.js

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
require('../mock/data');
var httpRequest = null;
var containerElem = document.getElementById('city-container');
var inputElem = document.getElementById('province');
inputElem.addEventListener('input', getCity);
function getCity(e) {
var province = e.target.value;
makeRequest(province);
}
function makeRequest(keyword) {
if (window.XMLHttpRequest) {
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
httpRequest = new ActiveXObject();
}
if (!httpRequest) {
alert('Giving up : Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = resolve;
httpRequest.open('GET', keyword + '.json', true);
httpRequest.send(null);
}
function resolve() {
var cityContainerElem = document.createElement('ul');
var cityData = null;
var cityElem = null;
var city = 'no data';
if (httpRequest.readyState === XMLHttpRequest.DONE) {
if (httpRequest.status === 200) {
cityData = JSON.parse(httpRequest.responseText).city;
for (var item in cityData) {
city = document.createTextNode(cityData[item]);
cityElem = document.createElement('li');
cityElem.appendChild(city);
cityContainerElem.appendChild(cityElem);
}
} else if (httpRequest.status === 404) {
city = document.createTextNode(city);
cityElem = document.createElement('li');
cityElem.appendChild(city);
cityContainerElem.appendChild(cityElem);
}
if (containerElem.childNodes.length !== 0) {
containerElem.replaceChild(cityContainerElem, containerElem.firstChild);
} else {
containerElem.appendChild(cityContainerElem);
}
}
}

同时我写的一个简单弹幕demo地址:https://github.com/Lucky4/barrage

参考:
https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX
https://xhr.spec.whatwg.org/
《锋利的JQuery》