文章目录
一、需求
在日常开发中,我们会经常用到 axios ,那么如何在自己的项目中自己封装 axios
二、分析
1. 安装axios
csharp
npm install axios
2. 新建一个 ts 文件,封装 axios
手写一个TS文件: src\utils\request.ts
,我的习惯把它放在 utils 目录下,源码如下
csharp
import axios, { InternalAxiosRequestConfig, AxiosResponse } from "axios";
import { useUserStoreHook } from "@/store/modules/user";
// 创建 axios 实例
const service = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 50000,
headers: { "Content-Type": "application/json;charset=utf-8" },
});
// 请求拦截器
service.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
const userStore = useUserStoreHook();
if (userStore.token) {
config.headers.Authorization = userStore.token;
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response: AxiosResponse) => {
const { code, msg } = response.data;
if (code === "00000") {
return response.data;
}
// 响应数据为二进制流处理(Excel导出)
if (response.data instanceof ArrayBuffer) {
return response;
}
ElMessage.error(msg || "系统出错");
return Promise.reject(new Error(msg || "Error"));
},
(error: any) => {
if (error.response.data) {
const { code, msg } = error.response.data;
// token 过期,重新登录
if (code === "A0230") {
ElMessageBox.confirm("当前页面已失效,请重新登录", "提示", {
confirmButtonText: "确定",
type: "warning",
}).then(() => {
localStorage.clear();
window.location.href = "/";
});
} else {
ElMessage.error(msg || "系统出错");
}
}
return Promise.reject(error.message);
}
);
// 导出 axios 实例
export default service;
3. store 存放 token 信息
我的 store 中存放了用户的登录信息,在封装 axios 时只用到了 token,因此下方代码可做参考
csharp
import { defineStore } from "pinia";
import { loginApi, logoutApi } from "@/api/auth";
import { getUserInfo } from "@/api/user";
import { resetRouter } from "@/router";
import { store } from "@/store";
import { LoginData } from "@/api/auth/types";
import { UserInfo } from "@/api/user/types";
import { useStorage } from "@vueuse/core";
export const useUserStore = defineStore("user", () => {
// state
const userId = ref();
const token = useStorage("accessToken", "");
const nickname = ref("");
const avatar = ref("");
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
const perms = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
/**
* 登录调用
*
* @param {LoginData}
* @returns
*/
function login(loginData: LoginData) {
return new Promise<void>((resolve, reject) => {
loginApi(loginData)
.then((response) => {
const { tokenType, accessToken } = response.data;
token.value = tokenType + " " + accessToken; // Bearer eyJhbGciOiJIUzI1NiJ9.xxx.xxx
resolve();
})
.catch((error) => {
reject(error);
});
});
}
// 获取信息(用户昵称、头像、角色集合、权限集合)
function getInfo() {
return new Promise<UserInfo>((resolve, reject) => {
getUserInfo()
.then(({ data }) => {
if (!data) {
return reject("Verification failed, please Login again.");
}
if (!data.roles || data.roles.length <= 0) {
reject("getUserInfo: roles must be a non-null array!");
}
userId.value = data.userId;
nickname.value = data.nickname;
avatar.value = data.avatar;
roles.value = data.roles;
perms.value = data.perms;
resolve(data);
})
.catch((error) => {
reject(error);
});
});
}
// 注销
function logout() {
return new Promise<void>((resolve, reject) => {
logoutApi()
.then(() => {
resetRouter();
resetToken();
location.reload(); // 清空路由
resolve();
})
.catch((error) => {
reject(error);
});
});
}
// 重置
function resetToken() {
token.value = "";
nickname.value = "";
avatar.value = "";
roles.value = [];
perms.value = [];
}
return {
token,
nickname,
avatar,
roles,
perms,
login,
getInfo,
logout,
resetToken,
/**
* 当前登录用户ID
*/
userId,
};
});
// 非setup
export function useUserStoreHook() {
return useUserStore(store);
}
4. 使用
csharp
import request from "@/utils/request";
import { AxiosPromise } from "axios";
import { UserForm, UserInfo, UserQuery } from "./types";
/**
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
*/
export function getUserInfo(): AxiosPromise<UserInfo> {
return request({
url: "/api/v1/users/me",
method: "get",
});
}
/**
* 添加用户
*
* @param data
*/
export function addUser(data: any) {
return request({
url: "/api/v1/users",
method: "post",
data: data,
});
}
/**
* 修改用户
*
* @param id
* @param data
*/
export function updateUser(id: number, data: UserForm) {
return request({
url: "/api/v1/users/" + id,
method: "put",
data: data,
});
}
/**
* 修改用户状态
*
* @param id
* @param status
*/
export function updateUserStatus(id: number, status: number) {
return request({
url: "/api/v1/users/" + id + "/status",
method: "patch",
params: { status: status },
});
}
/**
* 删除用户
*
* @param ids
*/
export function deleteUsers(ids: string) {
return request({
url: "/api/v1/users/" + ids,
method: "delete",
});
}
/**
* 下载用户导入模板
*
* @returns
*/
export function downloadTemplateApi() {
return request({
url: "/api/v1/users/template",
method: "get",
responseType: "arraybuffer",
});
}
/**
* 导出用户
*
* @param queryParams
* @returns
*/
export function exportUser(queryParams: UserQuery) {
return request({
url: "/api/v1/users/_export",
method: "get",
params: queryParams,
responseType: "arraybuffer",
});
}
/**
* 导入用户
*
* @param file
*/
export function importUser(deptId: number, file: File) {
const formData = new FormData();
formData.append("file", file);
return request({
url: "/api/v1/users/_import",
method: "post",
params: { deptId: deptId },
data: formData,
headers: {
"Content-Type": "multipart/form-data",
},
});
}
5. 文件 type.js
csharp
/**
* 用户查询对象类型
*/
export interface UserQuery {
keywords?: string;
status?: number;
deptId?: number;
}
/**
* 登录用户信息
*/
export interface UserInfo {
userId: number;
nickname: string;
avatar: string;
roles: string[];
perms: string[];
}
/**
* 用户表单类型
*/
export interface UserForm {
/**
* 用户头像
*/
avatar?: string;
/**
* 部门ID
*/
deptId?: number;
/**
* 邮箱
*/
email?: string;
/**
* 性别
*/
gender?: number;
/**
* 用户ID
*/
id?: number;
mobile?: string;
/**
* 昵称
*/
nickname?: string;
/**
* 角色ID集合
*/
roleIds?: number[];
/**
* 用户状态(1:正常;0:禁用)
*/
status?: number;
/**
* 用户名
*/
username?: string;
}