Vue项目中Axios全面封装实战指南
引言
在现代前端开发中,HTTP请求是应用与后端交互的核心环节。Axios作为目前最流行的HTTP客户端库,以其简洁的API和强大的功能受到广泛青睐。然而,直接在项目中裸用Axios会导致代码冗余、维护困难等问题。本文将深入探讨如何在Vue项目中全面封装Axios,打造企业级的HTTP请求解决方案。
一、为什么需要封装Axios?
1.1 直接使用Axios的问题
-
代码重复:每个请求都需要写完整的配置
-
维护困难:基础配置分散在各个文件中
-
缺乏统一错误处理
-
难以实现请求拦截和响应拦截的统一管理
-
类型安全缺失(TypeScript项目)
1.2 封装带来的优势
-
统一配置和管理
-
提高代码复用性
-
增强错误处理能力
-
便于实现请求拦截、身份验证等功能
-
提升开发效率和代码质量
二、基础封装实现
2.1 项目结构规划
src/
├── api/
│ ├── index.ts # 导出所有API
│ ├── request.ts # Axios封装核心
│ ├── types/ # 类型定义
│ │ ├── request.ts
│ │ └── response.ts
│ ├── modules/ # 模块化API
│ │ ├── user.ts
│ │ └── product.ts
│ └── interceptors/ # 拦截器
│ ├── request.ts
│ └── response.ts
2.2 创建基础请求类
// src/api/request.ts
import axios, {
AxiosInstance,
AxiosRequestConfig,
AxiosResponse,
InternalAxiosRequestConfig
} from 'axios';
import { RequestConfig, RequestInterceptors, CancelRequestSource } from './types';
class Request {
// axios实例
instance: AxiosInstance;
// 拦截器对象
interceptorsObj?: RequestInterceptors;
// 存储取消请求的Map
cancelRequestSource: CancelRequestSource;
// 存储所有请求url
requests: string[];
constructor(config: RequestConfig) {
this.instance = axios.create(config);
this.interceptorsObj = config.interceptors;
this.cancelRequestSource = {};
this.requests = [];
// 请求拦截器
this.instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
// 全局请求拦截器
console.log('全局请求拦截器');
// 添加取消令牌
const requestId = this.generateRequestId(config);
config.cancelToken = new axios.CancelToken(cancel => {
this.cancelRequestSource[requestId] = cancel;
});
this.requests.push(requestId);
// 自定义请求拦截器
if (this.interceptorsObj?.requestInterceptors) {
config = this.interceptorsObj.requestInterceptors(config);
}
return config;
},
(error: any) => {
return Promise.reject(error);
}
);
// 使用实例拦截器
this.instance.interceptors.request.use(
this.interceptorsObj?.requestInterceptors,
this.interceptorsObj?.requestInterceptorsCatch
);
// 响应拦截器
this.instance.interceptors.response.use(
(response: AxiosResponse) => {
const requestId = this.generateRequestId(response.config);
this.removeRequest(requestId);
// 全局响应拦截器
console.log('全局响应拦截器');
// 自定义响应拦截器
if (this.interceptorsObj?.responseInterceptors) {
response = this.interceptorsObj.responseInterceptors(response);
}
return response.data;
},
(error: any) => {
error.config && this.removeRequest(this.generateRequestId(error.config));
// 全局错误处理
if (this.interceptorsObj?.responseInterceptorsCatch) {
return this.interceptorsObj.responseInterceptorsCatch(error);
}
// HTTP状态码错误处理
if (error.response) {
this.handleHttpError(error.response.status, error.response.data);
}
// 请求被取消
if (axios.isCancel(error)) {
console.log('请求已被取消:', error.message);
return Promise.reject(new Error('请求已被取消'));
}
return Promise.reject(error);
}
);
// 使用实例响应拦截器
this.instance.interceptors.response.use(
this.interceptorsObj?.responseInterceptors,
this.interceptorsObj?.responseInterceptorsCatch
);
}
/**
* 生成请求唯一标识
*/
private generateRequestId(config: AxiosRequestConfig): string {
return `${config.url}-${JSON.stringify(config.params)}-${JSON.stringify(config.data)}`;
}
/**
* 移除已完成/取消的请求
*/
private removeRequest(requestId: string): void {
const requestIndex = this.requests.indexOf(requestId);
if (requestIndex > -1) {
this.requests.splice(requestIndex, 1);
}
delete this.cancelRequestSource[requestId];
}
/**
* 取消所有请求
*/
public cancelAllRequests(): v








