vue3 axios 的封装与 vue2 整体相同,细节需注意。整体思路可分为四步:
1、创建 axios 实例;
2、请求拦截器,携带 token 校验参数;
3、响应拦截器,剥离无效数据、处理 token 失效;
4、封装 axios 函数;
5、调用封装函数;
一、创建 axios 实例
const service = axios.create({
baseURL: '', // 所有的请求地址前缀部分
timeout: 60000, // 请求超时时间毫秒
withCredentials: true, // 异步请求携带cookie
headers: {
// 设置后端需要的传参类型
'Content-Type': 'application/json',
'token': 'your token',
'X-Requested-With': 'XMLHttpRequest',
},
});
二、添加请求拦截器
service.interceptors.request.use(
// eslint-disable-next-line func-names
function (config) {
// 在发送请求之前做些什么
const token = getToken();
if (token) {
if (!config.headers) {
config.headers = {};
}
config.headers.Authorization = `XXXX ${token}`;
}
// 若请求方式为post,则将data参数转为JSON字符串
if (config.method === 'POST') {
config.data = JSON.stringify(config.data);
}
return config;
},
// eslint-disable-next-line func-names
function (error) {
// 对请求错误做些什么
// eslint-disable-next-line no-console
console.log(error);
return Promise.reject(error);
}
);
三、添加响应拦截器
service.interceptors.response.use(
// eslint-disable-next-line func-names
function (response) {
return response.data;
},
// eslint-disable-next-line func-names
function (error) {
const code = error.response.status;
const dataAxios = error.response.data;
switch (code) {
case 400:
{
let msg = '';
Object.keys(dataAxios).forEach((k) => {
msg += `${k} - ${dataAxios[k].toString()}`;
});
Notification.error({
title: '数据提交异常!',
duration: 5000,
content: msg,
});
}
break;
case 401:
Notification.error({
title: '服务器消息',
duration: 5000,
content: 'Token 已过期,请重新登录!',
});
setToken('');
break;
case 403:
Notification.error({
title: '服务器消息',
duration: 5000,
content: 'Token 已过期,请重新登录!',
});
setToken('');
break;
case 404:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求地址出错!',
});
break;
case 408:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求超时!',
});
break;
case 500:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务器内部错误!',
});
break;
case 501:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务未实现!',
});
break;
case 502:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '网关错误!',
});
break;
case 503:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务不可用!',
});
break;
case 504:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '网关超时!',
});
break;
case 505:
Notification.error({
title: '服务器提示',
duration: 5000,
content: 'HTTP版本不受支持!',
});
break;
default:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求失败!',
});
}
return Promise.reject(error);
}
);
四、封装调用函数
/src/http/index.ts [ 完整代码 ]
import axios from 'axios';
import { getToken, setToken } from '@/utils/auth';
import { Notification } from '@arco-design/web-vue';
// 创建一个 axios 实例
const service = axios.create({
baseURL: '', // 所有的请求地址前缀部分
timeout: 60000, // 请求超时时间毫秒
withCredentials: true, // 异步请求携带cookie
headers: {
// 设置后端需要的传参类型
'Content-Type': 'application/json',
'token': 'your token',
'X-Requested-With': 'XMLHttpRequest',
},
});
// 添加请求拦截器
service.interceptors.request.use(
// eslint-disable-next-line func-names
function (config) {
// 在发送请求之前做些什么
const token = getToken();
if (token) {
if (!config.headers) {
config.headers = {};
}
config.headers.Authorization = `EIMS ${token}`;
}
// 若请求方式为post,则将data参数转为JSON字符串
if (config.method === 'POST') {
config.data = JSON.stringify(config.data);
}
return config;
},
// eslint-disable-next-line func-names
function (error) {
// 对请求错误做些什么
// eslint-disable-next-line no-console
console.log(error);
return Promise.reject(error);
}
);
// 添加响应拦截器
service.interceptors.response.use(
// eslint-disable-next-line func-names
function (response) {
return response.data;
},
// eslint-disable-next-line func-names
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
const code = error.response.status;
const dataAxios = error.response.data;
switch (code) {
case 400:
{
let msg = '';
Object.keys(dataAxios).forEach((k) => {
msg += `${k} - ${dataAxios[k].toString()}`;
});
Notification.error({
title: '数据提交异常!',
duration: 5000,
content: msg,
});
}
break;
case 401:
Notification.error({
title: '服务器消息',
duration: 5000,
content: 'Token 已过期,请重新登录!',
});
setToken('');
break;
case 403:
Notification.error({
title: '服务器消息',
duration: 5000,
content: 'Token 已过期,请重新登录!',
});
setToken('');
break;
case 404:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求地址出错!',
});
break;
case 408:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求超时!',
});
break;
case 500:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务器内部错误!',
});
break;
case 501:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务未实现!',
});
break;
case 502:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '网关错误!',
});
break;
case 503:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '服务不可用!',
});
break;
case 504:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '网关超时!',
});
break;
case 505:
Notification.error({
title: '服务器提示',
duration: 5000,
content: 'HTTP版本不受支持!',
});
break;
default:
Notification.error({
title: '服务器提示',
duration: 5000,
content: '请求失败!',
});
}
return Promise.reject(error);
}
);
export default service;
五、调用封装包
import axios from '@/http/index';
export function getData(pager: any, val: any) {
return axios({
url: `/api/data/?p=${pager.pageNum}&page_size=${pager.pageSize}&search=${val}`,
method: 'get',
});
}
export function Ambient(data: any, option: any, id: any) {
const method = option === 'add' ? 'post' : 'patch';
const url = option === 'add' ? '' : `${id}/`;
return axios({
url: `/api/data/${url}`,
method,
data,
});
}
export function delAmbient(id: any) {
return axios({
url: `/api/data/${id}/`,
method: 'delete',
});
}
参考:https://zhuanlan.zhihu.com/p/439486263