送人玫瑰,手有余香,你是什么,你的世界就是什么💡
网络上与axios相关的教程、以及源码解析有很多,还有健全的官方文档,本篇文章面向于初学axios库的开发者,目标是快速上手,如果觉得本篇文章帮助到了你,也就达到了这篇文章的目的😊
本文中使用的是Vue CLI3.0,安装依赖使用vue add命令进行
vue add axios
# yarn | npm安装
yarn add axios | npm install axios
this.axios.${方法名}.then().catch()
// 例子
this.axios.get(url,requestData).then((res)=>{
// 成功的回调
}).catch((err)=>{
// 失败的回调
});
/*
支持所有http请求以及请求取消、并发请求等功能,更多细节以及使用方法移步官方文档
文档: [axios文档](http://www.axios-js.com/zh-cn/docs/)
*/
接下来回到本文的重点,如何去合理的配置它以提高开发效率。本篇配置基于脚手架创建的axios.js进行修改
"use strict";
import Vue from 'vue';
import axios from "axios";
import store from '../store/index';
let config = {
// baseURL在此处省略配置,考虑到项目可能由多人协作完成开发,域名也各不相同,此处通过对api的抽离,域名单独配置在base.js中
// 请求超时时间
timeout: 60 * 1000,
// 跨域请求时是否需要凭证
// withCredentials: true, // Check cross-site Access-Control
heards:{
get:{
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
// 将普适性的请求头作为基础配置。当需要特殊请求头时,将特殊请求头作为参数传入,覆盖基础配置
},
post:{
'Content-Type': 'application/json;charset=utf-8'
// 将普适性的请求头作为基础配置。当需要特殊请求头时,将特殊请求头作为参数传入,覆盖基础配置
}
},
// 在向服务器发送请求前,对数据进行处理,axios默认会序列化数据
// transformRequest:[function(data){
//
// }],
// 在传递给 then/catch 前,修改响应数据
// transformResponse:[function(data){
//
// }]
};
/**
* 请求失败后的错误统一处理,当然还有更多状态码判断,根据自己业务需求去扩展即可
* @param {Number} status 请求失败的状态码
*/
const errorHandle = (status, other) => {
// 状态码判断
switch (status) {
// 401: 未登录状态,跳转登录页
case 401:
// 跳转登录页
break;
// 403 token过期
case 403:
// 如果不需要自动刷新token,可以在这里移除本地存储中的token,跳转登录页
break;
// 404请求不存在
case 404:
// 提示资源不存在
break;
default:
console.log(other);
}};
// 创建实例
const _axios = axios.create(config);
// 请求拦截器
_axios.interceptors.request.use(
function(config) {
// 从vuex里获取token
const token = store.state.token;
// 如果token存在就在请求头里添加
token && (config.headers.token = token);
return config;
},
function(error) {
// Do something with request error
error.data = {};
error.data.msg = "服务器异常";
return Promise.reject(error);
}
);
// 响应拦截器
_axios.interceptors.response.use(
function(response) {
// 清除本地存储中的token,如果需要刷新token,在这里通过旧的token跟服务器换新token,将新的token设置的vuex中
if(response.data.code===401){
localStorage.removeItem("token");
}
// 只返回response中的data数据
return response.data;
},
function(error) {
if(error){
// 请求已发出,但不在2xx范围内
errorHandle(error.status,error.data.msg);
return Promise.reject(error);
}else{
// 断网
return Promise.reject(error);
}
}
);
// eslint-disable-next-line no-unused-vars
Plugin.install = function(Vue, options) {
Vue.axios = _axios;
window.axios = _axios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios;
}
},
$axios: {
get() {
return _axios;
}
},
});
};
Vue.use(Plugin);
// 导出插件和_axios
export default {Plugin,_axios};
// main.js
import './plugins/axios'
为什么要进行API抽离?假设我们所有的请求都在业务代码中写this.$axios.get(),后期接口变更、有新的需求要多传参数过去,我们就要去业务代码里一个个去找然后进行修改,那将是一件很头疼的事。接下来带大家来实现API分离😃
将api接口根据功能划分为多个模块,利于多人开发,一个人负责一个模块的开发,方便日后接口的变更,将所有模块在此处引入,将引用暴露出去,然后挂载到Vue原型既可通过this.$api.模块名.方法名进行引用
/**
* api统一出口
* */
// 网站管理接口
import websiteManageAPI from './websiteManageAPI';
// 其他模块接口
// 导出接口
export default {
websiteManageAPI,
// ...
}
推荐命名格式为:模块名+APi,此文件用于将当前模块下的所有请求封装成对象,在使用时直接调用即可
/*
* 网站管理接口
* */
import services from '../plugins/axios'
import base from './base'; // 导入接口域名列表
const websiteManageAPI = {
// 登录
login(params){
return services._axios.post(`${base.lk}/login`,params);
},
// 测试post接口
postJSON(params){
return services._axios.post(`${base.lk}/getter/postJSON`,params);
},
// 测试get接口
getJSON(pageNo,pageSize){
return services._axios.get(`${base.lk}/getter/getJSON`,{params:{pageNo:pageNo,pageSize:pageSize}});
}
};
export default websiteManageAPI;
将每个开发者的接口地址封装成对象,在模块中进行引用时域名遇到变更,可直接修改此处的配置文件,快速修改为变更后的域名。
/*
* 接口域名管理
*
* */
const base = {
lk:"https://www.kaisir.cn/user",
other:"https://kf.kaisir.cn/api"
};
export default base;
将暴露出来的接口挂载到原型上,可方便接口的调用,当然你也可以按需加载,用到哪个模块的接口在在哪个模块下进行引用。
// 挂载到原型(main.js)
Vue.prototype.$api = api;
例如这样一个场景:后端的所有接口都需要登录后,根据成功登录返回的token进行访问。后端接口使用shiro+jwt实现接口鉴权和token发放
// App.vue,created生命周期
const token = localStorage.getItem("token");
//
if(lodash.isEmpty(token)){
// 跳转登录页:此处仅用于演示,用户名和密码为固定数据,实际需求为跳转登录页面进行授权
const userInfo = {
"username":"测试",
"password":"0x89oikklsa"
};
// 调用登录api
this.$api.websiteManageAPI.login(userInfo).then((res)=>{
// 将token进行存储并更新到vuex中
localStorage.setItem("token",res.token);
this.$store.state.token = res.token;
});
}else{
// 更新vuex中的token
this.$store.state.token = token;
}
// 测试其他接口能否调用成功
this.$api.websiteManageAPI.getJSON(1,3).then((res)=>{
console.log("接口调用成功");
console.log(res)
});
}