前言
Axios相信对前端熟悉的同学对它不会感到陌生了,这简直就是前端近年来的一大杀器,
官方推荐使用axios来进行网络请求,后面基本大部分项目都能瞧见它的身影。虽然axios很强,
但是单纯的axios并不能满足我们日常的使用,因此很多时候我们都需要对axios进行二次封装,
接下来我们就来详细讨论讨论。
为什么要二次封装axios
通常我们的项目会越做越大,页面也会越来越多,如果页面非常的少,直接用axios也没有什么大的影响,
那页面组件多了起来,上百个接口呢,这个时候后端改了接口,多加了一个参数什么的呢?那就只有找到那个页面,
进去修改.整个过程很繁琐不易于项目的维护和迭代.
这个时候如果我们统一的区管理接口,需要修改某一个接口的时候直接在api里修改对应的请求是不是很方便呢?
总结:api统一管理,不管接口有多少,所有的接口都可以非常清晰,容易维护.
初始化项目
yarn create vite
这里我们使用vite来初始化一个Vue项目
下载axios
yarn add axios
独立管理api接口
以图灵官网的接口为例
我们在项目中创建 api
文件夹用来管理所有的API,创建axios.js
文件二次封装axios.
//axios.js
import axios from "axios";
function myAxios(axiosConfig) {
const service = axios.create({
baseURL: "https://www.turingteam.me:8081", // 设置统一的请求前缀
timeout: 10000 // 设置统一的超时时长
});
return service(axiosConfig);
}
export default myAxios
这里的service(axiosConfig)
返回的是一个Promise对象
编写不同功能的api
如所有成员相关的API就放在 member.js
文件中,所有项目相关的API就放在 project.js
中,
这样子就很有条理性。
下面我们来 project.js
中编写获取项目列表的API。
//project.js
import myAxios from "../axios";
//团队项目查询
export function queryProjectAPI(offset, page) {
return myAxios({
url: "/guest/project/queryProject",
method: 'get',
params: {
offset,
page
}
})
}
//通过id查询团队项目详细信息
export function queryProjectByIdAPI(id) {
return myAxios({
url: "/guest/project/queryProjectById",
method: 'get',
params: {
id
}
})
}
在页面中具体使用
在 App.vue 文件中随便加一个按钮,点击触发请求。
<template>
<button @click="getList">点击</button>
</template>
<script lang='js'>
import {defineComponent} from 'vue'
import {queryProjectAPI} from '@/api/project.js';
export default defineComponent({
setup() {
const getList = async () => {
try{
let res = await queryProjectAPI(offset, page)
console.log(res);
}catch(error){
console.log(error);
}
}
return {
getList
}
}
})
</script>
到此,我们就封装了一个最简单的axios,我们每次新增加一个 API,只需要找到对应模块的 API 文件去添加即可,然后再到具体页面导入使用
POST请求参数序列化
在POST请求中的 Content-Type
常见的有以下3种形式:
Content-Type: application/json
Content-Type: application/x-www-form-urlencoded
Content-Type: multipart/form-data
现在主流基本在用application/json形式,Axios默认以这种形式工作,我们给后端接口传递参数也简单,直接丢在其data参数就行了。
我们在 resume.js
文件中编写简历API
import myAxios from "../axios";
//创新组内容填写
export function resumeInnovateAddAPI(data) {
return myAxios({
url: "/guest/resume/resumeInnovateAdd",
method: 'post',
data: data,
});
}
但是有时候后端要求Content-Type必须以application/x-www-form-urlencoded形式,那么通过上面传递的参数,后端是收不到的,我们必须对参数数据进行所谓的序列化处理才行,让它以普通表单形式(键值对)发送到后端,而不是json形式
import myAxios from "../axios";
//创新组内容填写
export function resumeInnovateAddAPI(data) {
return myAxios({
url: "/guest/resume/resumeInnovateAdd",
method: 'post',
data: data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
transformRequest: [
(data) => {
let result = ''
for (let key in data) {
result += encodeURIComponent(key) + '=' + encodeURIComponent(data[key]) + '&'
}
return result.slice(0, result.length - 1)
}
],
}
我通过 headers 来指定Content-Type的形式,对于 transformRequest 就是允许在向服务器发送前,修改请求数据,但只能用在 ‘PUT’,’POST’ 和 ‘PATCH’ 这几个请求方法,且后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream,更多的还有 transformResponse 能在传递给 then/catch 前,允许修改响应数据,其余更多参数的可以去 Axios文档查看。
请求拦截器&响应拦截器
1 请求拦截器
在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;
service.interceptors.request.use(function (config) {
// 在发送请求之前做些什么,例如加入token
.......
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
2 响应拦截器
同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。
service.interceptors.response.use(function (response) {
// 在接收响应做些什么
......
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
未完待续