axios封装实例
目录
一、封装 Axios 实例
二、环境变量配置(适配多环境)
三、API 接口统一管理
示例:src/api/user.js(用户相关接口)
四、在组件中使用
五、封装优势
六、扩展建议
在实际项目中,封装 Axios 实例是非常必要的做法。通过统一配置,可以简化请求逻辑、规范错误处理、便于维护(如统一修改 baseURL、添加全局 token 等)。下面是一个推荐的封装方案,包含完整的配置和使用示例:
一、封装 Axios 实例
首先创建 src/utils/request.js 文件,用于集中管理 Axios 配置:
import axios from 'axios';
import { ElMessage } from 'element-plus'; // 假设使用 Element Plus 提示组件(可替换为其他 UI 库)
import router from '@/router'; // 路由实例,用于 401 跳转登录// 1. 创建 Axios 实例
const request = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL, // 从环境变量获取 baseURL(适配开发/生产环境)timeout: 10000, // 超时时间(10秒)headers: {'Content-Type': 'application/json;charset=utf-8' // 默认请求头 最常用}
});// 2. 请求拦截器:添加 token、处理请求前逻辑
request.interceptors.request.use((config) => {// 从本地存储获取 token(根据项目实际存储方式调整)const token = localStorage.getItem('token');if (token) {// 添加 token 到请求头(格式根据后端要求调整,如 Bearer token)config.headers.Authorization = `Bearer ${token}`;}return config; // 必须返回配置},(error) => {// 请求参数错误(如配置错误)ElMessage.error('请求配置错误:' + error.message);return Promise.reject(error);}
);// 3. 响应拦截器:处理响应数据、统一错误提示
request.interceptors.response.use((response) => {// 假设后端返回格式为:{ code: 200, data: ..., message: '' }const { code, data, message } = response.data;// 成功状态:直接返回 data(简化业务层调用)if (code === 200) {return data;}// 非成功状态:统一提示错误信息(如参数错误、业务逻辑错误)ElMessage.error(message || '请求失败,请联系管理员');return Promise.reject(new Error(message || 'Error'));},(error) => {// 网络错误或 HTTP 状态码非 2xx(如 401、404、500)if (error.response) {// 服务器返回了响应,但状态码异常const { status, data } = error.response;switch (status) {case 401:// 未登录或 token 过期:清除 token 并跳转登录页localStorage.removeItem('token');router.push('/login?redirect=' + router.currentRoute.value.fullPath);ElMessage.error('登录已过期,请重新登录');break;case 403:ElMessage.error('没有权限访问');break;case 404:ElMessage.error('请求地址不存在');break;case 500:ElMessage.error('服务器内部错误');break;default:ElMessage.error(data?.message || `请求错误(${status})`);}} else if (error.request) {// 请求已发送,但未收到响应(如网络断开)ElMessage.error('网络错误,请检查网络连接');} else {// 请求配置错误(如未定义 URL)ElMessage.error('请求失败:' + error.message);}return Promise.reject(error); // 传递错误,便于业务层二次处理}
);// 4. 导出封装后的实例
export default request;
二、环境变量配置(适配多环境)
在项目根目录创建 .env.development(开发环境)和 .env.production(生产环境)文件,统一管理 baseURL:
env
# .env.development(开发环境)
VITE_API_BASE_URL = 'http://localhost:8888/api'
env
# .env.production(生产环境)
VITE_API_BASE_URL = 'https://api.example.com/api'
注:Vite 项目中环境变量需以
VITE_为前缀,通过import.meta.env访问。
三、API 接口统一管理
创建 src/api 目录,按模块拆分接口(如用户模块、商品模块),便于维护:
示例:src/api/user.js(用户相关接口)
import request from '@/utils/request';// 登录
export const login = (data) => {return request.post('/user/login', data);
};// 获取用户信息
export const getUserInfo = (id) => {return request.get(`/user/${id}`);
};// 更新用户信息
export const updateUser = (id, data) => {return request.put(`/user/${id}`, data);
};// 删除用户
export const deleteUser = (id) => {return request.delete(`/user/${id}`);
};
四、在组件中使用
在 Vue/React 组件中直接导入 API 方法,使用 async/await 处理异步逻辑:
vue
<!-- Vue 组件示例 -->
<template><button @click="handleLogin">登录</button>
</template><script setup>
import { ref } from 'vue';
import { login } from '@/api/user';const handleLogin = async () => {try {const formData = { username: 'admin', password: '123456' };// 调用接口(直接获取 data,无需再 .data 取值)const res = await login(formData);// 登录成功:存储 token 并跳转首页localStorage.setItem('token', res.token);router.push('/home');} catch (error) {// 错误已在拦截器处理,此处可做额外逻辑(如阻止表单重复提交)console.log('登录失败', error);}
};
</script>
五、封装优势
- 统一配置:baseURL、超时时间等全局配置,修改时只需改一处。
- 自动携带 token:请求拦截器统一添加认证信息,无需每个请求手动写。
- 错误集中处理:网络错误、401/500 等状态码统一提示,减少业务层重复代码。
- 简化数据获取:响应拦截器直接返回
data,业务层无需response.data取值。 - 环境适配:通过环境变量区分开发 / 生产环境的接口地址,避免手动切换。
六、扩展建议
- 请求加载状态:可在拦截器中添加
loading状态(如显示全局加载动画),请求结束后关闭。 - 重复请求取消:对于频繁触发的请求(如搜索输入),可通过
CancelToken取消上一次未完成的请求。 - 请求重试:对临时网络错误,可配置自动重试机制(如失败后重试 1-2 次)。
- 自定义配置:允许在单个请求中覆盖全局配置(如单独设置超时时间、禁用 token):
// 示例:某个请求需要更长的超时时间,且不需要 token request.get('/large-data', {timeout: 30000,headers: { Authorization: null } // 覆盖全局 token });
通过这种封装方式,既能保证代码的简洁性,又能提高项目的可维护性,。
