Appearance
Axios 网络请求
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。它是 Vue 项目中最常用的网络请求库之一。
为什么使用 Axios?
- 支持 Promise API:使用现代化的 Promise 语法
- 拦截器:可以在请求和响应前后添加拦截器
- 自动转换 JSON 数据:自动将响应数据转换为 JSON 格式
- 请求取消:支持取消正在进行的请求
- 超时处理:可以设置请求超时时间
- 错误处理:提供详细的错误信息
Axios 安装
bash
npm install axios基本使用
发送 GET 请求
javascript
import axios from 'axios'
// 基本 GET 请求
axios.get('https://api.example.com/users')
.then(response => {
console.log(response.data)
})
.catch(error => {
console.error('请求失败:', error)
})
// 带参数的 GET 请求
axios.get('https://api.example.com/users', {
params: {
page: 1,
limit: 10
}
})
.then(response => {
console.log(response.data)
})
.catch(error => {
console.error('请求失败:', error)
})发送 POST 请求
javascript
import axios from 'axios'
// 发送 POST 请求
axios.post('https://api.example.com/users', {
name: '张三',
age: 20,
email: 'zhangsan@example.com'
})
.then(response => {
console.log(response.data)
})
.catch(error => {
console.error('请求失败:', error)
})发送其他类型的请求
javascript
import axios from 'axios'
// PUT 请求
axios.put('https://api.example.com/users/1', {
name: '李四',
age: 21
})
// DELETE 请求
axios.delete('https://api.example.com/users/1')
// PATCH 请求
axios.patch('https://api.example.com/users/1', {
name: '王五'
})封装请求工具类
为了更好地管理 API 请求,我们可以封装一个请求工具类。
创建 axios 实例
javascript
// utils/request.js
import axios from 'axios'
// 创建 axios 实例
const request = axios.create({
baseURL: 'https://api.example.com', // 基础 URL
timeout: 10000, // 超时时间
headers: {
'Content-Type': 'application/json'
}
})
export default request添加请求拦截器
javascript
// utils/request.js
import axios from 'axios'
const request = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
// 请求拦截器
request.interceptors.request.use(
config => {
// 在发送请求之前做些什么
// 例如,添加 token
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
// 对请求错误做些什么
console.error('请求错误:', error)
return Promise.reject(error)
}
)
export default request添加响应拦截器
javascript
// utils/request.js
import axios from 'axios'
const request = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
// 请求拦截器
request.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
console.error('请求错误:', error)
return Promise.reject(error)
}
)
// 响应拦截器
request.interceptors.response.use(
response => {
// 对响应数据做点什么
return response.data
},
error => {
// 对响应错误做点什么
if (error.response) {
// 服务器返回错误状态码
switch (error.response.status) {
case 401:
// 未授权,跳转到登录页
window.location.href = '/login'
break
case 403:
// 禁止访问
console.error('禁止访问')
break
case 404:
// 资源不存在
console.error('资源不存在')
break
case 500:
// 服务器错误
console.error('服务器错误')
break
default:
console.error('请求失败')
}
} else if (error.request) {
// 请求已发送但没有收到响应
console.error('网络错误,无法连接到服务器')
} else {
// 请求配置出错
console.error('请求配置错误:', error.message)
}
return Promise.reject(error)
}
)
export default request使用封装的请求工具
javascript
// api/user.js
import request from '../utils/request'
export const getUserList = (params) => {
return request({
url: '/users',
method: 'get',
params
})
}
export const getUserById = (id) => {
return request({
url: `/users/${id}`,
method: 'get'
})
}
export const createUser = (data) => {
return request({
url: '/users',
method: 'post',
data
})
}
export const updateUser = (id, data) => {
return request({
url: `/users/${id}`,
method: 'put',
data
})
}
export const deleteUser = (id) => {
return request({
url: `/users/${id}`,
method: 'delete'
})
}跨域问题解决方案
什么是跨域?
跨域是指浏览器禁止从一个域名的网页去请求另一个域名的资源。这是浏览器的同源策略限制。
跨域解决方案
1. 后端设置 CORS
后端服务器可以设置 Access-Control-Allow-Origin 响应头来允许跨域请求。
javascript
// Express 示例
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')
if (req.method === 'OPTIONS') {
return res.status(200).end()
}
next()
})2. 前端使用代理
在开发环境中,可以使用 Vite 的代理功能来解决跨域问题。
javascript
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})然后,前端请求可以使用 /api 前缀:
javascript
// utils/request.js
const request = axios.create({
baseURL: '/api', // 使用代理路径
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})实战示例
用户管理系统
vue
<template>
<div>
<h2>用户管理</h2>
<!-- 添加用户 -->
<div class="add-user">
<h3>添加用户</h3>
<input v-model="newUser.name" placeholder="姓名">
<input v-model.number="newUser.age" type="number" placeholder="年龄">
<input v-model="newUser.email" placeholder="邮箱">
<button @click="addUser" :disabled="loading">添加</button>
</div>
<!-- 用户列表 -->
<div class="user-list">
<h3>用户列表</h3>
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="error" class="error">{{ error }}</div>
<ul v-else>
<li v-for="user in users" :key="user.id">
<div>{{ user.name }} ({{ user.age }}) - {{ user.email }}</div>
<button @click="editUser(user)">编辑</button>
<button @click="deleteUser(user.id)">删除</button>
</li>
</ul>
</div>
<!-- 编辑用户 -->
<div v-if="editingUser" class="edit-user">
<h3>编辑用户</h3>
<input v-model="editingUser.name" placeholder="姓名">
<input v-model.number="editingUser.age" type="number" placeholder="年龄">
<input v-model="editingUser.email" placeholder="邮箱">
<button @click="updateUser" :disabled="loading">更新</button>
<button @click="cancelEdit">取消</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getUserList, createUser, updateUser, deleteUser } from './api/user'
const users = ref([])
const loading = ref(false)
const error = ref('')
const newUser = ref({ name: '', age: 0, email: '' })
const editingUser = ref(null)
// 获取用户列表
async function fetchUsers() {
loading.value = true
error.value = ''
try {
users.value = await getUserList()
} catch (err) {
error.value = '获取用户列表失败'
console.error(err)
} finally {
loading.value = false
}
}
// 添加用户
async function addUser() {
if (!newUser.value.name || !newUser.value.email) {
error.value = '请填写姓名和邮箱'
return
}
loading.value = true
error.value = ''
try {
await createUser(newUser.value)
await fetchUsers()
// 清空表单
newUser.value = { name: '', age: 0, email: '' }
} catch (err) {
error.value = '添加用户失败'
console.error(err)
} finally {
loading.value = false
}
}
// 编辑用户
function editUser(user) {
editingUser.value = { ...user }
}
// 更新用户
async function updateUser() {
if (!editingUser.value.name || !editingUser.value.email) {
error.value = '请填写姓名和邮箱'
return
}
loading.value = true
error.value = ''
try {
await updateUser(editingUser.value.id, editingUser.value)
await fetchUsers()
editingUser.value = null
} catch (err) {
error.value = '更新用户失败'
console.error(err)
} finally {
loading.value = false
}
}
// 取消编辑
function cancelEdit() {
editingUser.value = null
}
// 删除用户
async function deleteUser(id) {
if (!confirm('确定要删除这个用户吗?')) {
return
}
loading.value = true
error.value = ''
try {
await deleteUser(id)
await fetchUsers()
} catch (err) {
error.value = '删除用户失败'
console.error(err)
} finally {
loading.value = false
}
}
// 组件挂载时获取用户列表
onMounted(() => {
fetchUsers()
})
</script>
<style scoped>
.add-user, .edit-user {
margin-bottom: 20px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
.user-list {
margin-top: 20px;
}
.loading, .error {
padding: 10px;
margin: 10px 0;
}
.error {
color: red;
background-color: #ffe6e6;
border: 1px solid #ffcccc;
border-radius: 4px;
}
ul {
list-style: none;
padding: 0;
}
li {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
input {
margin-right: 10px;
padding: 5px;
}
button {
margin-right: 5px;
padding: 5px 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f0f0f0;
cursor: pointer;
}
button:hover {
background-color: #e0e0e0;
}
button:disabled {
background-color: #f0f0f0;
cursor: not-allowed;
color: #999;
}
</style>通过本章的学习,我们掌握了 Axios 的基本使用方法,包括发送各种类型的请求、封装请求工具类、添加拦截器以及解决跨域问题等。Axios 是 Vue 项目中处理网络请求的重要工具,它提供了简洁的 API 和强大的功能,帮助我们更高效地与后端 API 进行交互。
