Ajax 简介

Ajax 的全称是 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),即在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式

XMLHttpRequest

XMLHttpRequest (简称 xhr)是浏览器提供的 JavaScript 对象,通过它,可以请求服务器上的数据资源

XMLHttpRequest 的基本使用

  1. 创建 xhr 对象
  2. 调用 xhr.open()函数
  3. 调用 xhr.send()函数
  4. 监听 xhr.onreadystatechange 事件

使用 xhr 发起 GET 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
// 3. 调用 send 函数
xhr.send();
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 获取服务器响应的数据
console.log(xhr.responseText);
}
};

readyState 属性

XMLHttpRequest 对象的 readyState 属性,用来表示当前 Ajax 请求所处的状态:

状态描述
0UNSENTXMLHttpRequest 对象已被创建,但尚未调用 opne()方法
1OPENEDopen()方法已经被调用
2HEADERS_RECEIVEDsend()方法已经被调用,响应头也已经被接收
3LOADING数据接收中,此时 response 属性中已经包含部分数据
4DONEAjax 请求完成,这意味着数据传输已经彻底完成或失败

使用 xhr 发起 POST 请求

  1. 创建 xhr 对象
  2. 调用 xhr.open()函数
  3. 设置 Content-Type 属性
  4. 调用 xhr.send()函数
  5. 监听 xhr.onreadystatechange 事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
// 3. 设置 Content-Type 属性
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 4. 调用 send 函数
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社');
// 5. 监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};

URL 编码与解码

  • encodeURI() 编码
  • decodeURI() 解码
1
2
3
4
5
6
var str = '黑马程序员';
var str2 = encodeURI(str);
console.log(str2);
console.log('----------');
var str3 = decodeURI('%E9%BB%91%E9%A9%AC');
console.log(str3);

JSON 数据交换格式

对象结构在 JSON 中表示为{}括起来的内容,即{ key1: value1, key2: value2 } 的键值对结构。其中 key 必须是使用英文的双引号包裹的字符串,value 的数据类型可以是数字、字符串、布尔值、null、数组、对象六种类型。

1
2
3
4
5
6
7
{
"name": "zs",
"age": 20,
"gender": "男",
"address": null,
"hobby": ["吃饭", "睡觉", "打豆豆"]
}

注意事项

  • 属性名必须使用双引号包裹
  • 字符串类型的值必须使用双引号包裹
  • JSON 中不能写注释
  • JSON 的最外层必须是对象或数组格式
  • 不能使用 undefined 或函数作为 JSON 的值

JSON 和 JS 对象的关系

JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。

1
2
3
4
5
//这是一个对象
var obj = { a: 'Hello', b: 'World' };

//这是一个 JSON 字符串,本质是一个字符串
var json = '{"a": "Hello", "b": "World"}';

JSON 和 JS 对象的互转

1
2
3
4
5
var obj = JSON.parse('{"a": "Hello", "b": "World"}');
//结果是 {a: 'Hello', b: 'World'}

var json = JSON.stringify({ a: 'Hello', b: 'World' });
//结果是 '{"a": "Hello", "b": "World"}'

序列化和反序列化

把数据对象转换为字符串的过程,叫做序列化,例如:调用 JSON.stringify() 函数的操作,叫做 JSON 序列化。
把字符串转换为数据对象的过程,叫做反序列化,例如:调用 JSON.parse() 函数的操作,叫做 JSON 反序列化。

1
2
3
4
5
6
7
8
9
10
11
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
console.log(typeof xhr.responseText);
var result = JSON.parse(xhr.responseText);
console.log(result);
}
};

XMLHttpRequest Level2

  1. 旧版 XMLHttpRequest 的缺点
  • 只支持文本数据的传输,无法用来读取和上传文件
  • 传送和接收数据时,没有进度信息,只能提示有没有完成
  1. XMLHttpRequest Level2 的新功能
  • 可以设置 HTTP 请求的时限
  • 可以使用 FormData 对象管理表单数据
  • 可以上传文件
  • 可以获得数据传输的进度信息

设置 HTTP 请求时限

使用 timeout 属性,设置一个最长等待时间,超过这个时限,就自动停止 HTTP 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var xhr = new XMLHttpRequest();

// 设置超时时间
xhr.timeout = 30;
// 设置超时以后的处理函数
xhr.ontimeout = function () {
console.log('请求超时了!');
};

xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
xhr.send();

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};

FormData 对象管理表单数据

Ajax 操作往往用来提交表单数据。为了方便表单处理,HTML5 新增了一个 FormData 对象,可以模拟表单操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 1. 创建 FormData 实例
var fd = new FormData();
// 2. 调用 append 函数,向 fd 中追加数据
fd.append('uname', 'zs');
fd.append('upwd', '123456');

var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
xhr.send(fd);

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};

FormData 对象也可以用来获取网页表单的值:

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
<body>
<form id="form1">
<input type="text" name="uname" autocomplete="off" />
<input type="password" name="upwd" />
<button type="submit">提交</button>
</form>

<script>
// 1. 通过 DOM 操作,获取到 form 表单元素
var form = document.querySelector('#form1');

form.addEventListener('submit', function (e) {
// 阻止表单的默认提交行为
e.preventDefault();

// 创建 FormData,快速获取到 form 表单中的数据
var fd = new FormData(form);

var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata');
xhr.send(fd);

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
};
});
</script>
</body>

上传文件

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
<body>
<!-- 1. 文件选择框 -->
<input type="file" id="file1" />
<!-- 2. 上传文件的按钮 -->
<button id="btnUpload">上传文件</button>
<br />
<!-- 3. img 标签,来显示上传成功以后的图片 -->
<img src="" alt="" id="img" width="800" />

<script>
// 1. 获取到文件上传按钮
var btnUpload = document.querySelector('#btnUpload');
// 2. 为按钮绑定单击事件处理函数
btnUpload.addEventListener('click', function () {
// 3. 获取到用户选择的文件列表
var files = document.querySelector('#file1').files;
if (files.length <= 0) {
return alert('请选择要上传的文件!');
}
var fd = new FormData();
// 将用户选择的文件,添加到 FormData 中
fd.append('avatar', files[0]);

var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar');
xhr.send(fd);

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
if (data.status === 200) {
// 上传成功
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url;
} else {
// 上传失败
console.log('图片上传失败!' + data.message);
}
}
};
});
</script>
</body>

显示文件上传进度

可以通过监听 xhr.upload.onprogress 事件,来获取到文件的上传进度

1
2
3
4
5
6
7
8
9
// 监听文件上传的进度
xhr.upload.onprogress = function (e) {
// 文件长度可计算
if (e.lengthComputable) {
// 计算出上传的进度
var procentComplete = Math.ceil((e.loaded / e.total) * 100);
console.log(procentComplete);
}
};

axios

Axios 是专注于网络数据请求的库,相比于原生的 XMLHttpRequest 对象,axios 简单易用,对比 jQuery 中的 ajax,axios 更轻量化。

axios 发起 GET 请求

类似于 jQuery 中的$.get()

1
2
3
4
5
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsObj = { name: 'zs', age: 20 };
axios.get(url, { params: paramsObj }).then(function (res) {
console.log(res.data);
});

axios 发起 POST 请求

类似于 jQuery 中的$.post()

1
2
3
4
5
var url = 'http://www.liulongbin.top:3006/api/post';
var dataObj = { address: '北京', location: '顺义区' };
axios.post(url, dataObj).then(function (res) {
console.log(res.data);
});

直接使用 axios 发起请求

类似于 jQuery 中的$.ajax()

  1. GET 请求
1
2
3
4
5
6
7
8
9
var url = 'http://www.liulongbin.top:3006/api/get';
var paramsData = { name: '钢铁侠', age: 35 };
axios({
method: 'GET',
url: url,
params: paramsData,
}).then(function (res) {
console.log(res.data);
});
  1. POST 请求
1
2
3
4
5
6
7
8
9
10
11
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: {
name: '娃哈哈',
age: 18,
gender: '女',
},
}).then(function (res) {
console.log(res.data);
});

form 表单的基本使用

1
2
3
4
5
6
<form>
<input type="text" name="email_or_mobile" />
<input type="password" name="password" />
<input type="checkbox" name="remember_me" checked />
<button type="submit">提交</button>
</form>

<form> 标签的属性

属性描述
actionURL 地址规定当提交表单时,向何处发送表单数据
methodget 或 post规定以何种方式把表单数据提交到 action URL
enctypeapplication/x-www-form-urlencoded
multipart/form-data、text/plain
规定在发送表单数据之前如何对其进行编码
target_blank、_self、_parent、_top、framename规定在何处打开 action URL
  1. action

action 属性用来规定当提交表单时,向何处发送表单数据,action 属性的值应该是后端提供的一个 URL 地址,这个 URL 地址专门负责接收表单提交过来的数据,如果 aciton 属性的值未指定,则默认为当前页面的 URL 地址。

  1. target
描述
_blank在新窗口打开
_self默认,在相同的框架中打开
_parent在父框架中打开
_top在整个窗口中打开
framename在指定的框架中打开
  1. method

method 属性用来规定以何种方式把表单数据提交到 action URL,它的可选值有两个,分别是 get 和 post,默认情况下,method 的值为 get,表示通过 URL 地址的形式,把表单数据提交到 action URL。

  • get 方式适合用来提交少量的、简单的数据。
  • post 方式适合用来提交大量的、复杂的、或包含文件上传的数据。
  • 在实际开发中,<form> 表单的 post 提交方式用的最多,很少用 get。例如登录、注册、添加数据等表单操作,都需要使用 post 方式来提交表单。
  1. enctype

enctype 属性用来规定在发送表单数据之前如何对数据进行编码。

描述
application/x-www-form-urlencoded在发送前编码所有字符(默认)
multipart/form-data不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain空格转换为 “+” 加号,但不对特殊字符编码。(很少用)
  • 在涉及到文件上传的操作时,必须将 enctype 的值设置为 multipart/form-data
  • 如果表单的提交不涉及到文件上传操作,则直接将 enctype 的值设置为 application/x-www-form-urlencoded 即可