Vue 4 中自定义 Axios 接口
在 Vue 4 项目中,合理封装 Axios 接口可以显著提高代码的可维护性和复用性。下面我将提供一个完整的自定义 Axios 接口实现方案,包括基础配置、拦截器封装、接口管理和错误处理等核心功能。
一、基础配置与安装
1. 安装 Axios
首先需要在项目中安装 Axios 依赖:
npm install axios
# 或
yarn add axios2. 创建基础 Axios 实例
在 src/utils/request.js 中创建基础 Axios 实例:
import axios from 'axios'
// 创建 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 从环境变量获取基础URL
timeout: 10000, // 请求超时时间
withCredentials: true // 允许跨域携带cookie
})
export default service二、拦截器封装
1. 请求拦截器
// 请求拦截器
service.interceptors.request.use(
config => {
// 在发送请求之前做些什么
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
// 添加自定义请求头
config.headers['X-Request-Id'] = generateUUID()
config.headers['X-Client-Type'] = 'web'
return config
},
error => {
// 对请求错误做些什么
return Promise.reject(error)
}
)2. 响应拦截器
// 响应拦截器
service.interceptors.response.use(
response => {
// 对响应数据做点什么
const res = response.data
// 自定义业务状态码处理
if (res.code !== 200) {
// 处理业务错误
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
// 对响应错误做点什么
if (error.response) {
// HTTP状态码处理
switch (error.response.status) {
case 401:
// 处理未授权
break
case 403:
// 处理禁止访问
break
case 404:
// 处理资源不存在
break
case 500:
// 处理服务器错误
break
default:
// 其他错误
}
}
return Promise.reject(error)
}
)三、接口统一管理
1. 创建 API 管理文件
在 src/api 目录下创建模块化的接口文件,例如 user.js:
import request from '@/utils/request'
// 用户登录
export function login(data) {
return request({
url: '/auth/login',
method: 'post',
data
})
}
// 获取用户信息
export function getInfo(userId) {
return request({
url: `/user/${userId}`,
method: 'get'
})
}
// 更新用户信息
export function updateUser(userId, data) {
return request({
url: `/user/${userId}`,
method: 'put',
data
})
}
// 删除用户
export function deleteUser(userId) {
return request({
url: `/user/${userId}`,
method: 'delete'
})
}2. 文件上传接口示例
// 文件上传
export function uploadFile(file) {
const formData = new FormData()
formData.append('file', file)
return request({
url: '/upload',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}四、在 Vue 4 组件中使用
1. 基本使用示例
<template>
<div>
<button @click="fetchUserData">获取用户数据</button>
<div v-if="loading">加载中...</div>
<div v-else>{{ userData }}</div>
</div>
</template>
<script>
import { getInfo } from '@/api/user'
export default {
data() {
return {
userData: null,
loading: false
}
},
methods: {
async fetchUserData() {
this.loading = true
try {
const response = await getInfo(123)
this.userData = response
} catch (error) {
console.error('获取用户数据失败:', error)
} finally {
this.loading = false
}
}
}
}
</script>2. 组合式 API 使用示例
<template>
<div>
<button @click="login">登录</button>
<div>{{ userInfo }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { login } from '@/api/user'
const userInfo = ref(null)
const login = async () => {
try {
const response = await login({
username: 'admin',
password: '123456'
})
userInfo.value = response
} catch (error) {
console.error('登录失败:', error)
}
}
</script>五、高级功能实现
1. 请求取消功能
import axios from 'axios'
const CancelToken = axios.CancelToken
let cancel
// 获取数据
export function getData(params) {
// 取消之前的请求
if (cancel) cancel()
return request({
url: '/data',
method: 'get',
params,
cancelToken: new CancelToken(function executor(c) {
cancel = c
})
})
}2. 请求重试机制
// 在响应拦截器中实现
service.interceptors.response.use(
response => response,
async error => {
const config = error.config
// 设置重试次数和当前重试次数
config.__retryCount = config.__retryCount || 0
const retryLimit = 3
// 检查是否达到重试限制
if (config.__retryCount >= retryLimit) {
return Promise.reject(error)
}
// 增加重试计数器
config.__retryCount += 1
// 创建新的Promise来处理指数退避
const delay = new Promise(resolve => {
setTimeout(() => {
resolve()
}, 1000 * config.__retryCount)
})
// 延迟后重试请求
await delay
return service(config)
}
)3. 请求缓存实现
const cacheMap = new Map()
export function getDataWithCache(params) {
const cacheKey = JSON.stringify(params)
if (cacheMap.has(cacheKey)) {
return Promise.resolve(cacheMap.get(cacheKey))
}
return request({
url: '/data',
method: 'get',
params
}).then(response => {
cacheMap.set(cacheKey, response)
return response
})
}六、全局配置与 TypeScript 支持
1. 全局配置示例
在 main.js 中:
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
const app = createApp(App)
// 全局配置
axios.defaults.baseURL = process.env.VUE_APP_API_BASE_URL
axios.defaults.timeout = 10000
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
app.use(VueAxios, axios)
app.mount('#app')2. TypeScript 类型定义
创建 src/types/axios.d.ts:
import axios from 'axios'
declare module 'axios' {
interface AxiosRequestConfig {
// 自定义配置项
retry?: number
retryDelay?: number
cache?: boolean
}
interface AxiosResponse<T = any> {
// 自定义响应结构
code: number
message: string
data: T
timestamp: number
}
}七、跨域解决方案
1. 开发环境代理配置
在 vue.config.js 中:
module.exports = {
devServer: {
proxy: {
'/api': {
target: ' http://backend.example.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
},
headers: {
'X-Proxy-Header': 'vue-dev-server'
}
}
}
}
}2. 生产环境 CORS 配置
确保后端服务器配置了正确的 CORS 头:
// Node.js Express 示例
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
res.header('Access-Control-Allow-Credentials', 'true')
if (req.method === 'OPTIONS') {
return res.sendStatus(200)
}
next()
})八、最佳建议
模块化组织:按业务模块拆分 API 文件,保持代码结构清晰
统一错误处理:在拦截器中实现全局错误处理,避免重复代码
合理使用拦截器:请求拦截器适合添加认证信息,响应拦截器适合处理通用业务逻辑
类型安全:使用 TypeScript 增强代码的可维护性和开发体验
性能优化:对于频繁请求且数据变化不频繁的接口,考虑实现缓存机制
安全考虑:敏感信息如 token 应存储在安全的地方(如 HttpOnly Cookie)
文档化:为每个接口添加清晰的注释说明参数和返回值
通过以上方案,您可以在 Vue 4 项目中实现一个功能完善、易于维护的自定义 Axios 接口系统。根据实际项目需求,您可以灵活调整各部分实现细节。
Vue 4 中自定义 Axios 接口
https://uniomo.com/archives/vue-4-zhong-zi-ding-yi-axios-jie-kou