文章目录
一、为什么要封装Axios?
在Vue项目中直接使用Axios存在以下问题:
- 多个组件重复编写相同的请求配置
- 缺乏统一的错误处理机制
- 难以维护和更新全局配置
- 无法快速切换不同环境接口地址
通过封装Axios可以实现:
✅ 统一管理接口地址
✅ 集中处理错误信息
✅ 添加全局Loading效果
✅ 简化组件中的使用方式
✅ 增强代码可维护性
二、完整封装实现步骤
1. 创建Axios实例
// src/utils/request.js
import axios from 'axios'
// 创建自定义实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 从环境变量读取基础地址
timeout: 15000 // 请求超时时间
})
2. 添加请求拦截器
// 请求拦截器
service.interceptors.request.use(
config => {
// 在发送请求前做些什么
if (store.getters.token) {
config.headers['Authorization'] = `Bearer ${store.getters.token}`
}
return config
},
error => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
3. 添加响应拦截器
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
// 自定义状态码验证(根据后端约定)
if (res.code !== 200) {
ElMessage.error(res.message || 'Error')
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
// 处理HTTP网络错误
let message = ''
if (error && error.response) {
switch (error.response.status) {
case 401:
message = "认证失败,请重新登录"
break
case 403:
message = "当前操作没有权限"
break
case 404:
message = "资源不存在"
break
default:
message = "网络异常,请稍后重试"
}
}
ElMessage.error(message)
return Promise.reject(error)
}
)
4. 封装通用请求方法
/**
* 通用请求方法
* @param {Object} options 请求配置
*/
function request(options) {
return service({
method: options.method || 'GET',
url: options.url,
data: options.data,
params: options.params,
...options
})
}
// 封装GET/POST快捷方法
export function get(url, params, options = {}) {
return request({
url,
params,
method: 'GET',
...options
})
}
export function post(url, data, options = {}) {
return request({
url,
data,
method: 'POST',
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
})
}
三、在Vue组件中使用
1. 发起请求
import { get, post } from '@/utils/request'
export default {
methods: {
// GET请求示例
async fetchData() {
try {
const res = await get('/api/user/list', { page: 1 })
console.log(res.data)
} catch (error) {
console.error(error)
}
},
// POST请求示例
async submitForm() {
const data = { username: 'admin', password: '123456' }
const res = await post('/api/login', data)
console.log(res.token)
}
}
}
四、高级扩展技巧
1. 文件上传处理
export function uploadFile(url, file) {
const formData = new FormData()
formData.append('file', file)
return post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
2. 添加全局Loading
let loadingInstance
service.interceptors.request.use(config => {
loadingInstance = ElLoading.service({ fullscreen: true })
return config
})
service.interceptors.response.use(response => {
loadingInstance.close()
return response
}, error => {
loadingInstance.close()
return Promise.reject(error)
})
3. 接口地址管理
创建单独的api配置文件:
// src/api/index.js
export default {
user: {
login: '/api/login',
getInfo: '/api/user/info',
list: '/api/user/list'
},
article: {
create: '/api/article/create'
}
}
五、项目结构建议
src/
├── api/ // 接口模块化管理
├── utils/
│ └── request.js // Axios封装文件
└── store/ // Vuex存储
六 、技术对比
下面是关于Fetch API、umi-request、jQuery.ajax和axios的对比表格:
Fetch API | umi-request | jQuery.ajax | axios | |
---|---|---|---|---|
技术基础 | 基于Promise的现代浏览器API | 基于fetch的封装,提供统一API和请求层治理 | 原生JavaScript中的XMLHttpRequest封装 | 基于Promise的HTTP客户端,封装XMLHttpRequest |
使用场景 | 适用于现代浏览器环境,进行网络请求 | 中台业务应用,提供统一请求库和接口治理 | 各种Web开发中需要异步请求的场景 | 浏览器和node.js环境,简化HTTP请求 |
语法简洁性 | 语法简洁,支持链式调用和Promise风格 | 简化了fetch的使用,提供统一API | 相对于原生XMLHttpRequest更简洁,但不如fetch简洁 | 语法简洁,支持Promise和async/await |
错误处理 | 使用.catch()处理错误,对网络错误敏感 | 提供统一的错误处理方式 | 需要手动处理错误,如请求超时、网络错误等 | 提供统一的错误处理方式,支持Promise的.catch() |
请求与响应 | 支持请求和响应对象,可自定义请求头和请求体 | 支持请求和响应对象,提供请求超时、缓存等内置功能 | 支持请求和响应对象,可自定义请求头和请求体 | 支持请求和响应对象,可自定义请求头和请求体 |
跨域请求 | 支持跨域请求,但需服务器支持CORS | 支持跨域请求,但需服务器支持CORS | 支持跨域请求,但需服务器支持CORS | 支持跨域请求,但需服务器支持CORS |
自动解析JSON | 默认情况下,响应数据会被自动解析为JSON对象 | 提供自动解析JSON的功能 | 需要手动解析JSON数据 | 自动转换JSON数据,无需手动解析 |
依赖项 | 无需额外库,浏览器原生支持 | 基于fetch的封装,需安装umi-request | 需要引入jQuery库 | 需安装axios库 |
功能丰富性 | 提供基本的网络请求功能 | 提供请求层治理、统一接口文档等功能 | 提供基本的Ajax请求功能 | 提供请求和响应拦截、取消请求等功能 |
社区支持 | 广泛使用的现代API,社区支持良好 | 适用于特定业务场景,社区支持可能因业务而异 | jQuery库广泛使用,Ajax功能也有良好支持 | 流行的HTTP客户端,社区支持良好 |
归纳:
- Fetch API:适合现代浏览器环境,语法简洁,支持Promise风格,但功能相对基础,需要手动处理一些高级功能。
- umi-request:基于fetch的封装,提供统一API和请求层治理,适用于中台业务应用,简化了fetch的使用,并提供了额外的内置功能。
- jQuery.ajax:依赖于jQuery库,提供了更简洁的Ajax请求方式,但引入jQuery库可能会增加项目体积。
- axios:功能丰富,支持Promise和async/await,适用于大型项目和复杂场景,提供了请求和响应拦截、取消请求等高级功能。
选择哪种技术取决于项目的需求、个人偏好以及项目的技术栈
七、总结
通过本文的封装方案,你可以获得:
- 统一的请求管理和错误处理
- 简洁的API调用方式
- 更好的代码维护性和扩展性
- 方便切换开发/生产环境
注意事项:
- 根据实际项目修改状态码判断逻辑
- 替换Element UI组件为你使用的UI库
- 完善TypeScript类型定义(推荐)
希望这篇实战指南能帮助你更好地组织Vue项目中的网络请求!如果有任何问题欢迎在评论区交流讨论。