本文已参与「新人创作礼」活动,一起开启掘金创作之路。
本文写于2018年7月,笔者当时正在为更换框架做准备,之前使用的是jQuery的.ajax,记一下遇到的问题及解决方案。
相关文档 官方文档 拦截+路由跳转demo
Q:用户登录信息,每个请求都需要带上的参数,使用繁琐还容易出错。所有请求路径预处理
A:使用默认配置 ,每次请求都会带上此数据
axios.defaults.data = {
uid: localStorage.uid,
};
设置baseURL
axios.defaults.baseURL = '/api';
Q:get方式和post方式传参使用不同的参数,get使用params,post使用data,使用麻烦
A:使用拦截器,在请求发出前拦截,统一处理参数,如果是get方式,则将data赋值给params
Q:post方式默认是json,目前后台识别的格式是application/x-www-form-urlencoded
A:使用官方推荐的方式,用qs.stringify处理data数据再发送,在请求拦截器里进行
axios.interceptors.request.use((config) => {
// Do something before request is sent
if (config && config.data) {
config.data = qs.stringify(config.data);
}
return config;
}
Q:在业务开发中,部分请求的数据一般不会变化,但使用次数缺比较频繁,希望将一部分指定请求缓存到本地,下次如果遇到相同参数的请求调用,直接返回本地缓存数据,不再从服务器上获取
A:对axios做了一层封装,将需要缓存的请求的url+参数处理成一个字符串作为key,存入sessionStorage里,当再次遇到该请求时,优先从sessionStorage获取数据返回,如果缓存中没有,则发起网络请求从服务端拉取数据
最后形成整体配置
import Vue from 'vue';
import axios from 'axios';
import qs from 'qs';
import bzt from '@/utils/bzt';
axios.defaults.baseURL = '';
if (process.env.NODE_ENV !== 'production') {
axios.defaults.baseURL = '/api';
}
const config = {
};
const urlParam = bzt.getParam();
/**
* axios的封装,带有本地缓存功能的axios,同时要求参数必须放在data里,规范url
* @param config 配置项
* @return {Promise<unknown>|*}
*/
const likeAxios = (config) => {
if (config.url && config.url.includes('?')) {
throw SyntaxError('url必须存在且不能包含?字符');
}
let cacheData = null;
config.data = config.data || {};
if (!config.withoutOtherParam) {
config.data.isAjax = true;
}
config.urlJson = `${config.url}?${qs.stringify(config.data)}`;
if (config.cache && window.sessionStorage) {
cacheData = window.sessionStorage.getItem(config.urlJson);
config.data.__cache = {
urlJson: config.urlJson,
}
}
if (cacheData) {
return getCacheData(config, cacheData);
} else {
return _axios(config);
}
};
/**
* 获取缓存数据
* @param config 配置信息
* @param cacheData 缓存数据库
* @return {Promise<unknown>}
*/
const getCacheData = (config, cacheData) => {
return new Promise ((resolve, reject) => {
let data = null;
try {
data = JSON.parse(cacheData);
}
catch (e) {
window.sessionStorage.removeItem(config.urlJson)
}
if (data) {
resolve(data);
} else {
_axios(config)
.then((result) => {
resolve(result);
})
.catch((e) =>{
reject(e);
});
}
});
};
const _axios = axios.create(config);
_axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
_axios.interceptors.request.use(
(config) => {
// Do something before request is sent
if (config) {
config.data = config.data || {};
if (config.data.__cache) {
config.__cache = config.data.__cache;
delete config.data.__cache;
}
if (config.method === 'get') {
config.params = config.data;
} else if (!config.formData) {
config.data = qs.stringify(config.data);
}
}
return config;
}
, error =>
// Do something with request error
Promise.reject(error),
);
_axios.interceptors.response.use((response) => {
// Do something with response data
if (response && response.data) {
// code === 4 代表未登录
if (!response.config.noRedirect && window.location.hostname !== 'localhost' && !response.data.success && response.data.code !== undefined && response.data.code === 4) {
if (window.sessionStorage) {
window.sessionStorage.setItem('goto', window.location.href);
}
window.location = '/web_pc/login.html';
}
return response.data;
}
return response;
}, error =>
// Do something with response error
Promise.reject(error));
Plugin.install = function (Vue, options) {
Vue.axios = likeAxios;
window.axios = likeAxios;
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return likeAxios;
},
},
$axios: {
get() {
return likeAxios;
},
},
});
};
Vue.use(Plugin);
export default Plugin;