Ajax 及其 Axios 的使用归纳
推荐使用 Axios
- Axios 是专注于网络数据请求的库。
- 相比于原生的 XMLHttpRequest 对象,axios 简单易用。
- 相比于 jQuery,axios 更加轻量化,只专注于网络数据请求。
传统的Ajax (XHR)
基本使用步骤
-
创建
xhr
对象 -
调用
xhr.open()
函数
- (POST 请求)设置
Content-Type
属性(固定写法)
-
调用
xhr.send()
函数 -
监听
xhr.onreadystatechange
事件GET请求
// 创建 xhr 对象
const xhr = new XMLHttpRequest()
// 调用 open 指定请求方式和 url 地址
// 带有参数可以使用查询字符串格式
// 请求地址URL用 ? 拼接
// 例如 id=1&&page=2
xhr.open('GET','https://www.baidu.com/api?id=1&&page=2')
// 调用 send 发起 Ajax 请求
xhr.send()
// 监听发起请求后的事件,onreadystatechange
xhr.onreadystatechange = function() {
// 监听
// 请求对象的请求状态 readyState
// 服务器响应状态 status
if(xhr.readyState === 4 && xhr.status === 200){
// responeseText响应回来的数据
console.log(xhr.responeseText)
}
}
POST请求
// // 创建 xhr 对象
const xhr = new XMLHttpRequest()
// 调用 open 指定请求方式和 url 地址
xhr.open('POST','https://www.baidu.com/api')
// 设置 Content-Type 属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 调用 send(),同时将数据以查询字符串的形式,提交给服务器
xhr.send('id=1&author=fantasy&page=2)
// 监听发起请求后的事件,onreadystatechange
xhr.onreadystatechange = function() {
// 监听
// 请求对象的请求状态 readyState
// 服务器响应状态 status
if(xhr.readyState === 4 && xhr.status === 200){
// responeseText响应回来的数据
console.log(xhr.responeseText)
}
}
XMLHttpRequest 对象的 readyState
属性,用来表示当前 Ajax 请求所处的状态。每个 Ajax 请求必然处于以下状态中的一个:
值 | 状态 | 描述 |
---|---|---|
0 | UNSENT | XMLHttpRequest 对象已被创建,但尚未调用 open方法。 |
1 | OPENED | open() 方法已经被调用。 |
2 | HEADERS_RECEIVED | send() 方法已经被调用,响应头也已经被接收。 |
3 | LOADING | 数据接收中,此时 response 属性中已经包含部分数据。 |
4 | DONE | Ajax 请求完成,这意味着数据传输已经彻底完成或失败。 |
设置 HTTP 请求时限
xhr.timeout = 3000
xhr.ontimeout = function(event){
alert('请求超时!')
}
设置 http 请求时限,3000毫秒,超时执行 ontimeout 的回调函数
FormDate 对象管理表单数据
基本使用
// 新建 FormData 对象
const fd = new FormDate()
// 添加数据 加入表单项
fd.append('id','12')
fd.append('name','fantasy')
// post 请求直接发送 FormData对象
// ...Ajax请求代码
xhr.send(fd)
获取网页 dom 表单的值
// 获取 dom 表单
const form = document.querySelector('#form')
// 监听表单提交
form.addEventListener('submit', function(e) {
// 阻止表单默认行为
e.preventDefault()
//根据 form 表单创建 FormData 对象,会自动将表单数据填充到 FormData 对象中
const fd = new FormData(form)
// post 请求直接发送 FormData对象
// ...Ajax请求代码
xhr.send(fd)
}
上传文件
// 1. 创建 FormData 对象
var fd = new FormData()
// 2. 向 FormData 中追加文件
fd.append('avatar', files[0])
// post 请求直接发送 FormData对象
// ...Ajax请求代码
xhr.send(fd)
监听 xhr.upload.onprogress 文件的上传进度
xhr.upload.onprogress = function(e) {
// e.lengthComputable 是一个布尔值,表示当前上传的资源是否具有可计算的长度
if (e.lengthComputable) {
// e.loaded 已传输的字节
// e.total 需传输的总字节
const percentComplete = Math.ceil((e.loaded / e.total) * 100)
}
}
监听 xhr.upload.onload 文件上传完成
xhr.upload.onload = function() {
$('#percent')
// 移除上传中的类样式
.removeClass()
// 添加上传完成的类样式
.addClass('progress-bar progress-bar-success')
}
jQuery-Ajax
浏览器中提供的 XMLHttpRequest 用法比较复杂,所以 jQuery 对 XMLHttpRequest 进行了封装,提供了一系列 Ajax 相关的函数,极大地降低了 Ajax 的使用难度。
常用方式
$.get()
$.get(url,[data],[callback])
参数名 | 参数类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 请求的地址 |
data | object | 否 | 请求传递的参数 |
callback | function | 否 | 请求成功的回调函数 |
// 例子
$.get('http://www.badui/api',{id:1,name:'fantasy'}, function(res) {
// 这里的 res 是服务器返回的数据
console.log(res)
})
$.post()
$.post(url,[data],[callback])
参数名 | 参数类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 请求的地址 |
data | object | 否 | 请求传递的参数 |
callback | function | 否 | 请求成功的回调函数 |
// 例子
$.post('http://www.badui/api',{id:1,name:'fantasy'}, function(res) {
// 这里的 res 是服务器返回的数据
console.log(res)
})
$.ajax()
$.ajax({
type: '', // 请求的方式,例如 GET 或 POST
url: '', // 请求的 URL 地址
data: { },// 这次请求要携带的数据
success: function(res) { } // 请求成功之后的回调函数
})
// 例子
$.ajax({
type: 'get', // 请求的方式,例如 GET 或 POST
url: 'http://www.badui/api', // 请求的 URL 地址
data: {id:1,name:'fantasy' },// 这次请求要携带的数据
success: function(res) { } // 请求成功之后的回调函数
})
FormDate 对象管理表单数据也适合 jQuery-Ajax
因为 FormDate 是 HTML5 新增的一个 对象,可以模拟表单操作
用法大致相同
拼接请求的根路径
建议新建 baseAPI.js
// 注意:每次调用 $.get() 或 $.post() 或 $.ajax() 的时候,
// 会先调用 ajaxPrefilter 这个函数
// 在这个函数中,可以拿到我们给Ajax提供的配置对象
$.ajaxPrefilter(function(options) {
// 在发起真正的 Ajax 请求之前,统一拼接请求的根路径
options.url = 'http://ajax.frontend.itheima.net' + options.url
})
统一为有权限的接口设置headers请求头
// 统一为有权限的接口,设置 headers 请求头
if (options.url.indexOf('/my/') !== -1) {
options.headers = {
Authorization: localStorage.getItem('token') || ''
}
}
// 全局统一挂载 complete 回调函数
// 不论请求成功还是失败,最终都会调用 complete 回调函数
options.complete = function(res) {
// 在 complete 回调函数中,可以使用 res.responseJSON 拿到服务器响应回来的数据
if (res.responseJSON.status === 1 && res.responseJSON.message === '身份认证失败!') {
// 1. 强制清空 token
localStorage.removeItem('token')
// 2. 强制跳转到登录页面
location.href = '/login.html'
}
}
Axios
axios.get
// 语法
axios.get('url',{params:{ 参数 } } ).then(callback)
// 例子
axios.get('url', {
params :{
id: 1,
name:'fantasy'
} //res.data 是服务器返回的数据
}).then(res => { consloe.log(res.data) })
参数名 | 参数类型 | 是否必选 | 说明 |
---|---|---|---|
url | string | 是 | 请求的地址 |
params | object | 否 | 请求传递的参数 |
callback | function | 否 | 请求成功的回调函数 |
axios.post
// 语法
axios.post('url',{ 参数 } ).then(callback)
// 例子
axios.post('url', {
id:1,
name:'fantasy'
}).then(res => { consloe.log(res.data) })
//res.data 是服务器返回的数据
axios
// 语法
axios({
// 使用 method 或 type 其中一种声明类型即可
method/type:'请求类型',
url:'请求地址',
data:{ post 数据 },
params:{ get 参数}
}).then(callback)
// 例子
axios({
method:'get',
url:'url',
params:{id:1,name:'fantasy'}
}).then(res => { consloe.log(res.data) })
配合 async / await 使用
axios返回的数据是一个Promise实例对象,用 .then()取到正确的数据
- async 关键字用于函数上(async函数的返回值是Promise实例对象)
- await 关键字用于 async 函数当中(await可以得到异步的结果)
// post 请求例子
document.querySelector('#btnPost').addEventListener('click', async function () {
// 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await!
// await 只能用在被 async “修饰”的方法中
// 解构赋值 把 axios 返回部分 解构出 data 重命名为 res
const { data: res } = await axios({
method: 'POST',
url: '/api/post',
data: {
name: 'fantasy',
id: 1
}
})
console.log(res)
})
vue 2.x 全局配置 axios
优点:每个组件可以通过 this.$http.get
直接发起请求,无需再导入 axios
;若根路径发生改变,只需修改 axios.defaults.baseURL
,有利于代码维护。
// main.js
// 配置请求根路径
axios.defaults.baseURL = 'http://api.com'
// 把 axios 挂载到 Vue 原型上
Vue.prototype.$http = aixos
缺点:无法实现 API
的复用。即多个组件需要对同一个接口发起请求,那么每个组件都需要重复书写 this.$http.get('/users')
类似的代码,造成冗余
改进:对于每一个根路径,独立封装一个 request.js
模块,组件导入所需根路径对应的 axios
进行使用
import axios from 'axios'
// 调用 axios.craete() 函数,request 接收 axios 实例对象
const request = axios.create({
baseURL: 'http://api.com'
})
export default request