简介
XMLHttpRequest 简称 xhr ,是浏览器提供的 Javascript 对象,通过它可以请求服务器上的数据资源,jQuery 中的 Ajax 函数,就是基于 xhr 对象封装出来的。
介绍 readyState 属性
XMLHttpRequest对象的readyState属性,用来表示当前 Ajax 请求所处的状态。每个 Ajax 请求必然处于以下状态中的一个:
| 值 | 状态 | 描述 |
|---|---|---|
| 0 | UNSENT | XMLHttpRequest 对象已被创建,但尚未调用 open 方法。 |
| 1 | OPENED | open() 方法已经被调用。 |
| 2 | HEADERS_RECEIVED | send() 方法已经被调用,响应头也已经被接收。 |
| 3 | LOADING | 数据接收中,此时 response 属性中已经包含部分数据。 |
| 4 | DONE | Ajax 请求完成,这意味着数据传输已经彻底完成或者失败。 |
发起 GET 请求
发起不带参数的 GET 请求
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数
xhr.open('get', url);
// 3. 调用 send 函数
xhr.send();
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
// 4.1 监听 xhr 对象的请求状态 readyState ; 与服务器响应状态 status
if (xhr.readyState !== 4 && xhr.status !== 200) return alert('请求失败');
// 4.2 查看或者使用响应回来的数据
console.log(xhr.responseText);
}
发起带参数的 GET 请求
发起带参数的 GET 请求只需要修改一步,因为 xhr 目前只有这一种方法来传递 GET 参数。
// ?id=1 就是传递的参数
// 多个参数:?id=1&name=zs&...
xhr.open('get', url + '?id=1');
编码/解码问题
URL 地址中,只允许出现英文相关的字母、标点符号、数字,因此在 URL 地址中不允许出现中文字符,如果 URL 中需要包含中文这样的字符,则必须对中文符号进行编码(转义)。
**URL 编码的原则:**使用安全的字符 (没有特殊用途或者特殊意义的可打印字符) 去表示那些不安全的字符。
**通俗理解:**使用去表示。
演示:
http://baidu.com?s=西游
// 经过 URL 编码后
http://baidu.com?s=%E8%A5%BF%E6%B8%B8
解决方法
浏览器提供了 URL 编码与解码的 API :
// 编码函数
encodeURL('西游'); // %E8%A5%BF%E6%B8%B8
// 解码函数
decodeURL('%E8%A5%BF%E6%B8%B8'); // 西游
发起 POST 请求
其中增加了设置 Content-Type 属性这一步骤,并且 POST 参数的传递在 send() 函数中进行。
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数
xhr.open('get', url);
// 3. 设置 Content-Type 属性
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 4. 调用 send 函数
xhr.send('id=1&name=zs&age=18');
// 5. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
// 5.1 监听 xhr 对象的请求状态 readyState ; 与服务器响应状态 status
if (xhr.readyState !== 4 && xhr.status !== 200) return alert('请求失败');
// 5.2 查看或者使用响应回来的数据
console.log(xhr.responseText);
}
注意:XMLHttpRequest返回的数据是字符串,想要进行使用必须经过处理。
以上即是 XMLHttpRequest 的基本使用。
封装 XMLHttpRequest
接下来,我来尝试一下封装一个简易版的 $.ajax() 方法,如果有不正确的地方希望大家指正。
// 封装数据处理函数 将 这样对象类型的数据处理成 id=1&name=zs&age=18 这样的数据
function jointObj(data) {
var let = [];
for (let key in data) {
arr.push(key + '=' + data[key]);
}
return arr.join('&');
}
// 最终使用的 ajax 函数
function myAjax(obj) {
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest();
if (obj.type.toUpperCase() == 'GET') {
// 2. 调用 open 函数
xhr.open('GET', obj.url + (obj.data ? '?' + jointObj(obj.data) : ''));
// 3. 调用 send 函数
xhr.send();
} else if (obj.type.toUpperCase() == 'POST') {
// 2. 调用 open 函数
xhr.open('POST', obj.url);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 3. 调用 send 函数
xhr.send(jointObj(obj.data));
}
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
// 4.1 监听 xhr 对象的请求状态 readyState ; 与服务器响应状态 status
if (xhr.readyState == 4 && xhr.status == 200) {
// 4.2 查看或者使用响应回来的数据
// 因为有些接口的数据可能不是个对象,所以我进行了是否是对象的判断
// 如果是找到 { 符号说明是对象,那就进行类型转换,将字符串转换成对象
// 如果不是就直接输出
var result = xhr.responseText.indexOf('{') !== -1 ? JSON.parse(xhr.responseText) : xhr.responseText;
obj.success(result);
};
}
}