axios的二次封装:在vue中如何灵活运用axios请求,二次封装更加灵活,更多参数可配置
axios请求的二次封装,以满足自身项目业务的需求。封装之前先需要准备以下6个依赖:
- store:作用是在登录失效的时候,调取store全局中的退出登录等方法,这里的逻辑可以根据自身需求修改,然后需要在封装中引入,详情查看代码。
- axios:这个就是最基础的,因为我们用的就是axios。安装命令
npm install axios --save
,然后需要在封装中引入,详情查看代码。 - router:在这里的作用是跳转401页面,要在封装中引入,详情查看代码。
- settings:这个是我自己写的配置基础参数的文件,贴在最后仅供参考。然后需要在封装中引入,详情查看代码。
- getToken:这个是获取或设置token的神器,这个可以自己封装,贴在最后仅供参考。然后需要在封装中引入,详情查看代码。
- {MessageBox, Notification,Loading} :这个就是element-ui中的组件,需要安装element-ui。具体安装等参考element-ui官网。需要在封装中引入,详情查看代码。
- qs:序列化参数,安装命令
npm install qs
。解决后端可能接受不到传的参数,然后需要在封装中引入,详情查看代码。
话不多说,直接上代码:
request.js:
/**
* axios请求封装
*/
import store from '../store'
import axios from 'axios'
import router from '@/router/routers'
import settings from '../settings'
import { getToken } from '@/utils/auth'
import qs from 'qs'
import { MessageBox, Notification, Loading } from 'element-ui'
// 基础参数配置
let base = {
cType: 1, //1 'application/json' 2 'application/x-www-form-urlencoded' 默认1
successCode: 0, //请求成功的code 默认0
succeedMsg: null, // 请求成功后code为successCode的提示 为true的时候就用后端返回的文字 默认null
erroredMsg: true, // 请求成功后code不是successCode的提示 为true的时候就用后端返回的文字 默认true
loginLoseCode: 401, // 登录失效的code 默认401
loading: {
instance: null, // 加载实例 默认无
type: 1, // 0不显示加载 1全局加载 2局部加载 默认1
options: {
target: 'document.body'
}
}
};
// let loadingInstance = Loading.service();
// 创建axios实例
const service = axios.create({
baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : '/api', // api 的 base_url
timeout: settings.timeout, // 请求超时时间
})
// http请求拦截
service.interceptors.request.use(config => {
base.succeedMsg = config.succeedMsg ? config.succeedMsg : null;
base.erroredMsg = config.erroredMsg ? config.erroredMsg : true;
base.cType = config.cType ? config.cType : 1;
base.successCode = config.successCode ? config.successCode : 0;
base.loginLoseCode = config.loginLoseCode ? config.loginLoseCode : 0;
base.loading.type = config.loadingType ? config.loadingType : 0;
base.loading.options.target = config.loadingTarget ? config.loadingTarget : 'document.body';
if (base.loading.type != 0) base.loading.instance = Loading.service(base.loading.options);
if (config.method == 'GET' || config.method == 'get') {
if (!/\?/.test(config.url)) {
let str = splitJoint(config.data);
config.url += str;
}
}
if (getToken()) {
config.headers['token'] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
}
switch (base.cType) {
case 1:
config.headers['Content-Type'] = 'application/json';
break;
case 2:
config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
config.data = qs.stringify(config.data); // 序列化,否则后端可能接受不到传的参数
break;
default:
config.headers['Content-Type'] = 'application/json';
break;
}
return config
}, error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
});
function splitJoint(obj) {
let arr = [];
for (let key in obj) {
arr.push(key + '=' + obj[key]);
}
return arr.length > 0 ? '?' + arr.join('&') : '';
}
// response 拦截器
service.interceptors.response.use(response => {
if (base.loading.instance) base.loading.instance.close();
const code = response.status
if (code < 200 || code > 300) {
Notification({
title: '失败',
message: '接口请求失败',
type: 'error'
})
return Promise.reject('error')
} else {
if (base.successCode == response.data.code && base.succeedMsg) {
Notification({
title: '成功',
message: base.succeedMsg == true ? response.data.msg : base.succeedMsg,
type: 'success'
})
return response.data;
} else if (base.successCode != response.data.code && base.erroredMsg) {
Notification({
title: '失败',
message: base.erroredMsg == true ? response.data.msg : base.erroredMsg,
type: 'error'
})
return Promise.reject(response.data);
}
return response.data;
}
}, error => {
if (base.loading.instance) base.loading.instance.close();
let code = 0;
try {
code = error.response.data.status
} catch (e) {
if (error.toString().indexOf('Error: timeout') !== -1) {
Notification({
title: '失败',
message: '网络请求超时',
type: 'error'
})
return Promise.reject(error)
}
}
if (code) {
if (code === base.loginLoseCode) {
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
store.dispatch('LogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
} else if (code === 403) {
router.push({ path: '/401' })
} else {
const errorMsg = error.response.data.message
if (errorMsg !== undefined) {
Notification({
title: '失败',
message: errorMsg,
type: 'error'
})
}
}
} else {
Notification({
title: '失败',
message: '接口请求失败',
type: 'error'
})
}
return Promise.reject(error)
})
export default service;
使用方法:
import request from '@/utils/request'
request({
url: '/sys/login',
method: 'POST',
data,
succeedMsg:true,
erroredMsg:true,
loadingType:1,
loadingTarget:document.querySelector('.dd')//这个值不传默认body显示
}).then(res=>{}).catch(err=>{})
需要注意的5个地方:
- 基础参数可配置,可以根据自己的需求进行修改或传参:
2.此处的Content-Type根据需求来扩展,这里使用了传参判断使用哪种:
- 请求后的提示,这里取的提示字段可能需要根据业务后台返回的字段来修改:
- 登录失效后的逻辑需要根据业务灵活处理,此处可修改成自己的逻辑:
- 这里需要有自己401页面,根据业务需求修改:
- loadingTarget参数作为局部加载的时候传的选择器,页面初次加载的时候只有在this.$nextTick(()=>{})中才会生效,意思就是等待节点挂载上才能获取到,否则默认在body上显示加载。
可参考的依赖文件:
settings.js:
module.exports = {
/**
* @description 网站标题
*/
title: '测试',
/**
* @description 是否显示 tagsView
*/
tagsView: false,
/**
* @description 固定头部
*/
fixedHeader: true,
/**
* @description 记住密码状态下的token在Cookie中存储的天数,默认1天
*/
tokenCookieExpires: 1,
/**
* @description 记住密码状态下的密码在Cookie中存储的天数,默认1天s
*/
passCookieExpires: 1,
/**
* @description 是否只保持一个子菜单的展开
*/
uniqueOpened: true,
/**
* @description token key
*/
TokenKey: 'HEALTH-CARD-TOEKN',
/**
* @description 请求超时时间,毫秒(默认2分钟)
*/
timeout: 1200000,
/**
* @description 是否显示logo
*/
sidebarLogo: true,
/**
* 是否显示登录页面设置的底部信息
*/
showLoginFooter: true,
/**
* 是否显示设置的底部信息
*/
showFooter: false,
/**
* 底部文字,支持html语法
*/
footerTxt: '© 2020 v1.0.0 测试 ',
/**
* 备案号
*/
caseNumber: '',
/**
* 技术支持
*/
technicalSupport: '测试',
/**
* 是否加密密码 https://blog.csdn.net/qq_37346607/article/details/85237368
*/
encryption: true
}
auth.js:这里需要自己安装js-cookie依赖
import Cookies from 'js-cookie'
import Config from '@/settings'
const TokenKey = Config.TokenKey
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token, rememberMe) {
if (rememberMe) {
return Cookies.set(TokenKey, token, { expires: Config.tokenCookieExpires })//Config.tokenCookieExpires
} else return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
结束啦,有任何问题可以私聊我~