文章目录
- 一、需求
- 二、分析
- 1. 安装axios
- 2. 新建一个 ts 文件,封装 axios
- 3. store 存放 token 信息
- 4. 使用
- 5. 文件 type.js
一、需求
在日常开发中,我们会经常用到 axios ,那么如何在自己的项目中自己封装 axios
二、分析
1. 安装axios
npm install axios
2. 新建一个 ts 文件,封装 axios
手写一个TS文件: src\utils\request.ts
,我的习惯把它放在 utils 目录下,源码如下
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,因此下方代码可做参考
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", () => {// stateconst 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.xxxresolve();}).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. 使用
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
/*** 用户查询对象类型*/
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;
}