https://www.doubao.com/thread/w476d78a62be8a4ce
網(wǎng)絡(luò)請求封裝方案
在Vue項(xiàng)目中,我們通常使用axios作為HTTP客戶端,并對其進(jìn)行封裝以簡化請求流程、統(tǒng)一錯(cuò)誤處理和請求攔截。以下是一個(gè)完整的網(wǎng)絡(luò)請求封裝方案:
1. 安裝axios
npm install axios --save
2. 創(chuàng)建請求配置和封裝
在src目錄下創(chuàng)建utils/request.js文件,用于封裝axios:
// src/utils/request.js
import axios from 'axios';
import { ElMessage } from 'element-plus';
// 創(chuàng)建axios實(shí)例
const service = axios.create({
? baseURL: import.meta.env.VITE_APP_BASE_API, // 從環(huán)境變量中獲取API基礎(chǔ)路徑
? timeout: 5000, // 請求超時(shí)時(shí)間
? headers: {
? ? 'Content-Type': 'application/json;charset=utf-8',
? },
});
// 請求攔截器
service.interceptors.request.use(
? (config) => {
? ? // 在發(fā)送請求之前做些什么
? ? // 例如:添加token、設(shè)置請求頭等
? ?
? ? const token = localStorage.getItem('token');
? ? if (token) {
? ? ? config.headers['Authorization'] = `Bearer ${token}`;
? ? }
? ?
? ? return config;
? },
? (error) => {
? ? // 對請求錯(cuò)誤做些什么
? ? console.log(error);
? ? return Promise.reject(error);
? }
);
// 響應(yīng)攔截器
service.interceptors.response.use(
? (response) => {
? ? // 對響應(yīng)數(shù)據(jù)做些什么
? ? const res = response.data;
? ?
? ? // 根據(jù)業(yè)務(wù)需求判斷響應(yīng)狀態(tài)
? ? if (res.code !== 200) {
? ? ? ElMessage({
? ? ? ? message: res.message || 'Error',
? ? ? ? type: 'error',
? ? ? ? duration: 3000,
? ? ? });
? ? ?
? ? ? // 例如:401表示未登錄,跳轉(zhuǎn)到登錄頁
? ? ? if (res.code === 401) {
? ? ? ? // 跳轉(zhuǎn)到登錄頁的邏輯
? ? ? ? localStorage.removeItem('token');
? ? ? ? window.location.href = '/login';
? ? ? }
? ? ?
? ? ? return Promise.reject(new Error(res.message || 'Error'));
? ? } else {
? ? ? return res;
? ? }
? },
? (error) => {
? ? // 對響應(yīng)錯(cuò)誤做些什么
? ? console.log('err' + error); // for debug
? ?
? ? let message = error.message;
? ? if (error.response) {
? ? ? // 根據(jù)不同的HTTP狀態(tài)碼返回不同的錯(cuò)誤信息
? ? ? const status = error.response.status;
? ? ? message = `請求錯(cuò)誤(${status})`;
? ? ?
? ? ? switch (status) {
? ? ? ? case 400:
? ? ? ? ? message = '錯(cuò)誤請求';
? ? ? ? ? break;
? ? ? ? case 401:
? ? ? ? ? message = '未授權(quán),請重新登錄';
? ? ? ? ? break;
? ? ? ? case 403:
? ? ? ? ? message = '拒絕訪問';
? ? ? ? ? break;
? ? ? ? case 404:
? ? ? ? ? message = '請求錯(cuò)誤,未找到該資源';
? ? ? ? ? break;
? ? ? ? case 500:
? ? ? ? ? message = '服務(wù)器端出錯(cuò)';
? ? ? ? ? break;
? ? ? ? default:
? ? ? ? ? message = `連接錯(cuò)誤(${status})`;
? ? ? }
? ? } else if (error.message.includes('timeout')) {
? ? ? message = '請求超時(shí)';
? ? } else {
? ? ? message = '連接服務(wù)器失敗';
? ? }
? ?
? ? ElMessage({
? ? ? message: message,
? ? ? type: 'error',
? ? ? duration: 3000,
? ? });
? ?
? ? return Promise.reject(error);
? }
);
// 封裝常用的請求方法
export default {
? get(url, params = {}) {
? ? return service.get(url, { params });
? },
?
? post(url, data = {}) {
? ? return service.post(url, data);
? },
?
? put(url, data = {}) {
? ? return service.put(url, data);
? },
?
? delete(url, params = {}) {
? ? return service.delete(url, { params });
? },
};
3. 配置環(huán)境變量
在項(xiàng)目根目錄創(chuàng)建.env.development和.env.production文件,分別配置開發(fā)和生產(chǎn)環(huán)境的API基礎(chǔ)路徑:
# .env.development
VITE_APP_BASE_API = 'http://localhost:3000/api'
# .env.production
VITE_APP_BASE_API = 'https://production-api.com/api'
4. 創(chuàng)建API模塊
在src目錄下創(chuàng)建api文件夾,用于組織各個(gè)模塊的API請求:
// src/api/user.js
import request from '@/utils/request';
export function login(data) {
? return request.post('/user/login', data);
}
export function getUserInfo() {
? return request.get('/user/info');
}
export function logout() {
? return request.post('/user/logout');
}
5. 在組件中使用API
<!-- src/views/Login.vue -->
<template>
? <div class="login-container">
? ? <el-form :model="loginForm" ref="loginRef" label-width="80px">
? ? ? <el-form-item label="用戶名">
? ? ? ? <el-input v-model="loginForm.username" placeholder="請輸入用戶名"></el-input>
? ? ? </el-form-item>
? ? ? <el-form-item label="密碼">
? ? ? ? <el-input v-model="loginForm.password" type="password" placeholder="請輸入密碼"></el-input>
? ? ? </el-form-item>
? ? ? <el-form-item>
? ? ? ? <el-button type="primary" @click="handleLogin">登錄</el-button>
? ? ? </el-form-item>
? ? </el-form>
? </div>
</template>
<script setup>
import { ref } from 'vue';
import { login } from '@/api/user';
const loginForm = ref({
? username: '',
? password: '',
});
const loginRef = ref(null);
const handleLogin = async () => {
? try {
? ? const { data } = await login(loginForm.value);
? ? localStorage.setItem('token', data.token);
? ? ElMessage.success('登錄成功');
? ? // 跳轉(zhuǎn)到首頁
? } catch (error) {
? ? console.error('登錄失敗', error);
? }
};
</script>
封裝特點(diǎn)和優(yōu)勢
1.統(tǒng)一錯(cuò)誤處理:在攔截器中統(tǒng)一處理錯(cuò)誤,避免在每個(gè)組件中重復(fù)編寫錯(cuò)誤處理代碼
2.請求攔截:自動(dòng)添加token等請求頭信息
3.環(huán)境配置:區(qū)分開發(fā)環(huán)境和生產(chǎn)環(huán)境的API地址
4.模塊化組織:按功能模塊組織API請求,使代碼結(jié)構(gòu)更清晰
5.Promise風(fēng)格:使用async/await語法,使異步請求更簡潔
6.可擴(kuò)展性:可以輕松添加更多功能,如請求重試、上傳進(jìn)度等
你可以根據(jù)實(shí)際項(xiàng)目需求進(jìn)一步擴(kuò)展這個(gè)封裝,例如添加請求緩存、請求取消、上傳下載等功能。