Axios 封装小记

开发思路远比开发流程及工具更重要。

开发中一个很重要的思想就是工程化,在我理解,工程化落实到实际开发中,最直观的体现就是封装, js 我们会封装函数库, sass 我们会封装常用的 @mixin ,等等。

这次就针对 Vue 中使用的 Axios ,对它进行一次封装。

为什么要封装 Axios

一个 Web 应用离不开 HTTP 请求,早期用 jQuery $.ajax() 的时候,我就会在 $.ajax() 外面再封装一层,主要做的处理有统一接口地址和返回状态处理。

因为不这么做,那在每个业务模块里使用 $.ajax() 的时候,就需要分别去处理,代码复用性很低,如果是比较大的项目,多人协作开发,后期维护会非常可怕。

所以即便是现在换了 Vue 开发, $.ajax() 换成了 Axios ,也还是离不开封装,下面就看下我是怎么封装 Axios 的吧。

封装 Axios

直接看代码吧。

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import axios from 'axios';
import qs from 'qs';
import router from '@/router/index';
import store from '@/store/index';

const api = axios.create({
baseURL: '',
timeout: 10000,
responseType: 'json'
});

// request 拦截
api.interceptors.request.use(request => {
if (request.method == 'post') {
if (request.data instanceof FormData) {
if (store.getters['token/isLogin']) {
// 如果是 FormData 类型(上传图片)
request.data.append('token', store.state.token);
}
} else {
// 带上 token
if (request.data == undefined) {
request.data = {};
}
// 从 vuex 里获取 token 数据
if (store.getters['token/isLogin']) {
request.data.token = store.state.token.token;
}
// 序列化 POST 类型的数据
request.data = qs.stringify(request.data);
}
} else {
// 带上 token
if (request.params == undefined) {
request.params = {};
}
// 从 vuex 里获取 token 数据
if (store.getters['token/isLogin']) {
request.params.token = store.state.token.token;
}
}
return request;
});

// response 拦截
api.interceptors.response.use(
response => {
if (response.data.error != '') {
// 鉴权,如果未登录则跳转到登录页
if (response.data.status == 0) {
router.push({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
return false;
}
// 错误提示,可更换其他消息提示组件
swal({
icon: 'error',
title: '系统错误',
text: response.data.error,
timer: 2000,
button: false
});
return Promise.reject(response.data);
}
return Promise.resolve(response.data);
},
error => {
return Promise.resolve(error);
}
);

export { axios, api };

可以看到 request 拦截器主要就做了一件事,就是如果 token 存在,则在请求里把 token 带上。 response 拦截器也只做一件事,就是在获取到返回参数后先判断接口是否报错,并给出错误提示,如果错误是未登录,则跳转到登录页。

使用

在 main.js 里直接引入,并将 api 和 axios 挂载到 Vue 的原型上,这样在页面上就可以通过 this.$apithis.$axios 直接使用了,无需再引入 api 文件。

1
2
3
4
// main.js
import { api, axios } from './api';
Vue.prototype.$api = api;
Vue.prototype.$axios = axios;

这里你可能会有疑问,不是已经封装了 axios ,为什么还要把 axios 挂载到 Vue 的原型上?原因很简单,因为我需要用到 axios 并发函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
this.$axios
.all([
this.$api.get('banner/list', {
params: {
id: 1
}
}),
this.$api.get('banner/list', {
params: {
id: 2
}
})
])
.then(
this.$axios.spread((acct, perms) => {
// 请求之后处理
})
);

最后

以前整过一套 Gulp 的工程化工作流,现在换到 Vue 了,虽然两者不是同一类型的产物,但我还是尝试也整了一套 Vue 的开发工作流。

这篇文章封装的 Axios 自然也在其中,当然还有其他特性,比如更完整的鉴权体系、精灵图、页面刷新等等,不了解一下吗?

参考

vue 中 Axios 的封装和 API 接口的管理