前言
在项目中正确封装 aixos 可以使我们日常开发事半功倍,下面对这方面配置做一下自我总结,欢迎各位阅读指教。
全局安装
//npm install
npm install axios -g
引入使用
//main.js
import axios from 'axios'
axios.post("url",{}).then((res) => {
// 数据处理
}).catch((error) => {
// 错误处理
});
配置
下面介绍怎么样的 axios 配置才是相对合理的,使我们日后维护减少不必要的麻烦,提升开发效率。
事实上这种配置上的东西单独抽出一个文件出来会更好,这也符合模块化的思想。因此我们新建一个配置文件service.js
,此文件对外 export 一个 axios 实例,只需在main.js
文件中引入即可。
import axios from "axios";
// 导入vuex,需要获取里面存储的token,请求时带上token,保证接口安全
import store from "../store";
const config = {
// api
baseURL: 'https://some-domain.com/api/',
// 请求超时时间
timeout: 60 * 1000,
// 请求header
headers: {'X-Custom-Header': 'foobar'},
// `cancelToken` specifies a cancel token that can be used to cancel the request
cancelToken: new CancelToken(function (cancel) {})
// 跨域请求时是否需要凭证,这个配置和后台相关
// withCredentials: true, // Check cross-site Access-Control
// 在向服务器发送请求前,对数据进行处理,axios默认会序列化数据
// transformRequest:[function(data){
//
// }],
// 接口返回后,对响应进行处理
// transformResponse:[function(data){
//
// }]
};
//自定义错误处理
const errorHandle = (status, msg) => {
// 状态码判断
switch (status) {
// 401: 未登录状态,跳转登录页
case 401:
// 跳转登录页
break;
// 403 token过期
case 403:
//移除本地存储中的token,跳转登录页
break;
// 404请求不存在
case 404:
// 提示资源不存在
break;
default:
console.log(msg);
}
};
// 创建实例
const service = axios.create(config);
// 请求拦截器
service.interceptors.request.use(
function(config) {
// 从vuex里获取token
// 例如这样一个场景:后端的所有接口都需要登录后,根据成功登录返回的token进行访问。
// 后端接口使用shiro+jwt实现接口鉴权和token发放
const token = store.state.token;
// 如果token存在就在请求头里添加
token && (config.headers.token = token);
return config;
},
function(error) {
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
function(response) {
// 清除本地存储中的token
if (response.data.code === 401) {
localStorage.removeItem("token");
//
}
if (response.status === 200) {
//数据处理
return response.data;
}
},
function(error) {
if (error) {
errorHandle(error.status, error.data.msg);
return Promise.reject(error);
}
}
);
export default service;
上述配置便是 axios 的核心配置,我们来看看都做了哪些事情。
- 设置超时时间
- 请求头的集中配置
- 响应失败后对状态码进行统一处理
- 在请求拦截中添加 token
- 在响应拦截中对 token 过期以及返回数据进行相应处理
- 接口域名抽离
- 最后将其导出,我们抽离 API 时会用到
接口划分
可以通过将接口按功能或业务划分进一步来细化我们的项目管理,方便团队协作。
-
创建接口模块文件,将具体的接口地址、参数、请求方式等写在此处,最后将其导出方便 api 统一出口文件引用。
-
创建 api 统一出口文件,将 api 接口根据功能划分为多个模块,利于多人开发,将所有模块在此处引入,将引用暴露出去,然后挂载到 Vue 原型上,方便全局使用
具体实现起来也很简单,只需要在 src 目录下创建 api 文件夹,按需要拆分出不同接口模块,最后统一引入index.js
文件即可
//user.js
import service from 'service'
export default {
login(data) {
return service({
url: '/login',
method: 'post',
data
})
}
}
//index.js
// 用户接口
import user from './user';
// 其他模块接口
...
// 导出接口
export default {
user,
// ...
}
自动化引入
当拆分模块过多时还可以使用自动化引入,主要使用 require.context 实现前端工程化动引入文件。
这个在注册组件的时候经常用到,我们把组件全部写在 components 文件夹下,然后创建 componentRegister.js 使用 require.context 进行组件注册
require.context(directory, useSubdirectories = false, regExp = /^.//)
比如:
require.context('./router',true,/\.routes\.js/
可以理解为获取 router 文件下以.routes.js 结尾的文件,知道这个以后,就可以在项目动态引入文件,方便使用了
//index.js
import Vue from "vue";
const apiList = [];
function importAll(r) {
r.keys().forEach((key) => {
apiList.push(r(key).default);
});
}
importAll(require.context("../api", true, /\.js/));//这里的目录和规则可以看自己习惯,这里获取的是api下以.js结尾的文件
export default {
...apiList
};
最后
-
欢迎各位评论探讨^_^
-
参考链接
小贴士:
- axios.defaults.withCredentials = true
- 这一条要求在请求头里带上 cookie! 如果前端配置了这个 withCredentials=true,后段设置 Access-Control-Allow-Origin 不能为 "*",必须是你的源地址