平时都是用axios封装的ajax函数去发起ajax请求,那我们是否可以使用原生js去封装并发起ajax请求呢?答案是完全可以的。要封装属于自己的ajax函数,首先要知道axios的原理是基于new出来的XMLHttpRequest实例对象来发起ajax请求的,而XMLHttpRequest是浏览器内置的一个构造函数。那么意味着我们便可以直接通过js来使用这个构造函数。在使用XMLHttpRequest发起请求的时候要使用.open()、.setRequestHeader()、.send()函数去分别传递请求的行头体。
一、请求体格式和对应的Content-Type值
为了方便服务器接收数据,当提交请求体时,需要指定一个叫做Content-Type的请求头,使用axios不用关心请求头,因为axios帮我们处理好了加请求。但是想用原生js代码封装自己的ajax函数就需要自己指定,所以要了解下面3种不同的请求体格式和与之对应的Content-Type。
| 请求体格式 | Content-Type | 是否需要在代码中指定 |
|---|---|---|
| 参数=值&参数=值 | application/x-www-form-urlencoded | 是 |
| '{ "id": 1, "name": "zs" }' | application/json | 是 |
| new FormData() | multipart/form-data; xxxxxxxxx随机字符 | 否,浏览器自动设置 |
二、封装ajax函数主要分为下面几个步骤:
- 定义myAjax这个自定义函数,接受method, url, params, data, success这几个主要参数。
- 创建
XMLHttpRequest的实例对象xhr - 单独为get添加判断条件,为唯一不一样的params拼接url
- 调用
xhr.open()函数发送请求method和url路径 - 处理其他data请求体数据,根据不同的请求体数据,设置对应的请求头的
Content-Type类型。 - 调用
xhr.setRequestHeader()函数:(GET请求比较特殊,它不用请求头) - 调用
xhr.send()函数:(GET请求调用send不用传递数据或直接用send传递null)
三、实现
//由于params的到的值是对象,所以要把它变成字符串用&拼接一起,方便后续放
//进url传递到服务器端
function parseObjectToString(obj) {
let arr = []
for (let key in obj) {
arr.push(key + '=' + obj[key])
}
return arr.join('&')
}
//接收method, url, params, data, success这几个主要参数
function myaxios({ method, url, params, data, success }) {
//创建XMLHttpRequest对象
let xhr = new XMLHttpRequest()
//判断是否为get请求和是否有传递params数据
if (method.toLowerCase() == 'get' && params) {
//拼接参数到url的末端
url += '?' + parseObjectToString(params)
}
//发送对应的method和url请求
xhr.open(method, url)
//判断data的数据类型,分别调用不同的请求头类型
if (data instanceof FormData) {
//如果是FormData对象就直接传递data发送请求,不需要指定请求头类型
xhr.send(data)
} else if (typeof data == 'object') {
//如果data是对象,就要指定Content-Type为
//application/json的请求头类型
xhr.setRequestHeader('Content-Type', 'application/json')
//把对象转换成JSON字符串发送
xhr.send(JSON.stringify(data))
} else if (typeof data == 'string') {
//如果data是字符串,就要指定Content-Type为
//application/x-www-form-urlencoded的请求头类型
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
//直接发送字符串
xhr.send(data)
} else {
//单独为get请求发送无参的send()
xhr.send()
}
//使用回调函数获取服务器端响应信息
xhr.addEventListener('load', function () {
success(JSON.parse(xhr.response))
})
}