目标:掌握在Vue3中规范地发起HTTP请求
1. 安装与基础配置
bash
npm install axios
javascript
// src/utils/request.js
import axios from 'axios'
const service = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000
})
export default service
2. 基础请求示例
html
<script setup>
import request from '@/utils/request'
import { ref } from 'vue'
const data = ref(null)
// GET请求
const fetchData = async () => {
try {
const res = await request.get('/posts')
data.value = res.data
} catch (error) {
console.error('请求失败:', error)
}
}
// POST请求
const submitForm = async (formData) => {
await request.post('/submit', formData)
}
</script>
3. 请求/响应拦截器
javascript
// 请求拦截(添加Token)
service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截(统一错误处理)
service.interceptors.response.use(
response => response.data,
error => {
if (error.response.status === 401) {
router.push('/login')
}
return Promise.reject(error)
}
)
4. 请求封装优化
javascript
// src/api/user.js
import request from '@/utils/request'
export const login = (data) => {
return request({
url: '/user/login',
method: 'POST',
data
})
}
export const getUserInfo = () => {
return request.get('/user/info')
}
5. 与Pinia结合使用
javascript
// stores/user.js
import { defineStore } from 'pinia'
import { login, getUserInfo } from '@/api/user'
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
userInfo: null
}),
actions: {
async loginAction(credentials) {
const res = await login(credentials)
this.token = res.token
},
async loadUserInfo() {
this.userInfo = await getUserInfo()
}
}
})
6. 跨域处理(开发环境)
javascript
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
最佳实践:
- 统一错误处理:
javascript
// 在拦截器中全局处理
const showError = (message) => {
ElMessage.error(message || '请求异常')
}
- 取消重复请求:
javascript
// 使用axios.CancelToken避免重复请求
const pendingRequests = new Map()
const addPending = (config) => {
const key = `${config.method}-${config.url}`
config.cancelToken = new axios.CancelToken(cancel => {
if (!pendingRequests.has(key)) {
pendingRequests.set(key, cancel)
}
})
}
- Loading状态管理:
html
<script setup>
const isLoading = ref(false)
const fetchData = async () => {
isLoading.value = true
try {
// ...请求逻辑
} finally {
isLoading.value = false
}
}
</script>