# 如何用Vue封裝Axios請求
## 前言
在現代前端開發中,網絡請求是必不可少的部分。Axios作為當前最流行的HTTP客戶端之一,以其簡潔的API和強大的功能被廣泛使用。而在Vue項目中,合理地封裝Axios不僅能提高代碼復用性,還能統一管理請求邏輯。本文將詳細介紹如何在Vue項目中優雅地封裝Axios請求。
## 一、為什么需要封裝Axios
### 1.1 原始Axios使用的痛點
直接使用Axios雖然簡單,但在實際項目中會面臨:
- 每個請求都需要重復配置基礎URL、headers等
- 缺乏統一的錯誤處理機制
- 難以集中管理API接口
- 不方便添加全局loading狀態
- 難以實現請求取消等功能
### 1.2 封裝帶來的優勢
通過封裝可以實現:
- **統一配置**:基礎路徑、超時時間等
- **攔截器管理**:請求/響應攔截處理
- **API集中管理**:所有接口統一維護
- **更好的擴展性**:便于添加新功能
## 二、基礎封裝實現
### 2.1 創建axios實例
首先在項目中創建`src/utils/request.js`文件:
```javascript
import axios from 'axios'
// 創建axios實例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // 從環境變量獲取基礎URL
timeout: 10000 // 請求超時時間
})
// 請求攔截器
service.interceptors.request.use(
config => {
// 在發送請求前可以做些什么
// 例如:添加token
const token = localStorage.getItem('token')
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
},
error => {
// 對請求錯誤做些什么
return Promise.reject(error)
}
)
// 響應攔截器
service.interceptors.response.use(
response => {
// 對響應數據做點什么
const res = response.data
// 假設后端返回的數據格式為 { code: 200, data: {}, message: '' }
if (res.code !== 200) {
// 處理業務錯誤
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res.data
}
},
error => {
// 對響應錯誤做點什么
if (error.response) {
// 處理HTTP狀態碼錯誤
switch (error.response.status) {
case 401:
// 跳轉到登錄頁
break
case 403:
// 提示權限不足
break
case 404:
// 資源不存在
break
case 500:
// 服務器錯誤
break
}
}
return Promise.reject(error)
}
)
export default service
創建src/api
目錄,按模塊劃分API:
// src/api/user.js
import request from '@/utils/request'
export function login(data) {
return request({
url: '/user/login',
method: 'post',
data
})
}
export function getUserInfo() {
return request({
url: '/user/info',
method: 'get'
})
}
在請求攔截器中:
let loadingInstance
service.interceptors.request.use(config => {
loadingInstance = Loading.service({
lock: true,
text: '加載中...',
background: 'rgba(0, 0, 0, 0.7)'
})
return config
})
service.interceptors.response.use(
response => {
loadingInstance.close()
return response
},
error => {
loadingInstance.close()
return Promise.reject(error)
}
)
const pendingMap = new Map()
const getPendingKey = (config) => {
return [config.method, config.url].join('&')
}
service.interceptors.request.use(config => {
const key = getPendingKey(config)
if (pendingMap.has(key)) {
const cancel = pendingMap.get(key)
cancel()
pendingMap.delete(key)
}
config.cancelToken = new axios.CancelToken(cancel => {
pendingMap.set(key, cancel)
})
return config
})
service.interceptors.response.use(response => {
const key = getPendingKey(response.config)
pendingMap.delete(key)
return response
})
const retryDelay = 1000 // 重試延遲
const retryCount = 3 // 最大重試次數
service.interceptors.response.use(undefined, error => {
const config = error.config
if (!config || !config.retry) return Promise.reject(error)
config.__retryCount = config.__retryCount || 0
if (config.__retryCount >= retryCount) {
return Promise.reject(error)
}
config.__retryCount += 1
return new Promise(resolve => {
setTimeout(() => resolve(service(config)), retryDelay)
})
})
import { login } from '@/api/user'
export default {
methods: {
async handleLogin() {
try {
const res = await login({
username: 'admin',
password: '123456'
})
console.log('登錄成功', res)
} catch (error) {
console.error('登錄失敗', error)
}
}
}
}
// store/modules/user.js
import { login, getUserInfo } from '@/api/user'
const actions = {
login({ commit }, userInfo) {
return new Promise((resolve, reject) => {
login(userInfo).then(res => {
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
})
}
}
完整的封裝示例可以參考以下結構:
src/
├── api/
│ ├── user.js
│ ├── product.js
│ └── ...
├── utils/
│ ├── request.js
│ └── ...
通過合理的封裝,我們可以將Axios的強大功能與Vue的響應式特性完美結合,構建出健壯、易維護的網絡請求層。本文介紹的方法只是基礎實現,實際項目中可以根據需求進一步擴展和完善。希望本文能幫助你更好地組織Vue項目中的網絡請求代碼。 “`
這篇文章總計約1900字,涵蓋了從基礎封裝到高級技巧的完整內容,采用Markdown格式編寫,包含代碼塊、標題層級和列表等標準Markdown元素。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。