在现代前端开发中,与后端 API 进行数据交互是必不可少的环节。Vue3 作为当前最流行的前端框架之一,虽然本身不包含 HTTP 请求功能,但我们可以通过集成 Axios 来实现强大的网络请求能力。本文将从零开始,详细介绍如何在 Vue3 项目中使用 Axios,涵盖基础用法到高级技巧的完整内容
一、Axios简介:为什么选择它
1.1 什么是Axios
Axios 是一个基于 Promise 的 HTTP 客户端,可用于浏览器和 Node.js 环境。它本质上是对原生 XMLHttpRequest 的封装,但采用了 Promise 的实现方式,符合最新的 ES 规范
1.2 Axios的主要特点
① 支持浏览器和 Node.js:一套代码可以在前后端通用
② Promise API:支持 async / await 语法,代码更简洁
③ 拦截请求和响应:可以在请求发送前和响应返回后进行统一处理
④ 自动转换 JSON 数据:无需手动解析 JSON 响应
⑤ 客户端防止 XSRF:提供了 XSRF 保护机制
⑥ 请求取消:支持取消正在进行的请求
⑦ 自动转换请求和响应数据:简化数据处理流程
1.3 为什么在 Vue3 中选择 Axios
Vue 本身专注于视图层,不包含 HTTP 请求功能。Vue 官方在 2.0 版本后,不再维护 vue-resource,并推荐使用 Axios。选择 Axios 的主要原因包括:
① 解耦性好:Axios 与 Vue 没有直接耦合,可以轻松地在任何项目中使用
② 功能强大:丰富的 API 和强大的功能(如拦截器、实例创建)满足复杂项目需求
③ 社区活跃:生态完善,遇到问题容易找到解决方案
④ TypeScript 支持:提供完整的 TypeScript 类型定义
二、Axios 安装与基础配置
2.1 安装 Axios
在 Vue3 项目中安装 Axios 非常简单:
npm install axios
# 或
yarn add axios
对于简单的非工程化页面,也可以通过 CDN 引入:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
2.2 在 Vue3 中引入 Axios 的三种方式
方式一:局部引入
此方式适合简单项目,在需要使用的组件中直接引入:
import axios from 'axios';
export default {
setup() {
const fetchData = async () => {
try {
const response = await axios.get('/api/data');
console.log(response.data);
} catch (error) {
console.error(error);
}
};
return { fetchData };
}
};
方式二:全局挂载
在 main.js 中将 Axios 挂载到 Vue 实例原型上:
import { createApp } from 'vue';
import axios from 'axios';
import App from './App.vue';
const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.mount('#app');
此方法不推荐使用,理由:
① 污染全局命名空间 ② 在Composition API 的setup 函数中访问不便
③ 不利于类型检查
方式三:封装为模块
推荐使用此方式,创建专门的模块来封装 Axios,这是最佳实践:
// src/utils/request.js
import axios from 'axios';
// 创建Axios实例
const service = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 5000, // 请求超时时间
headers: {
'Content-Type': 'application/json'
}
});
export default service;
在组件中使用:
import request from '@/utils/request';
export default {
setup() {
const fetchData = async () => {
try {
const response = await request.get('/posts');
console.log(response.data);
} catch (error) {
console.error(error);
}
};
return { fetchData };
}
};
2.3 基本配置选项详解
Axios 提供了丰富的配置选项,常用的包括:
const config = {
url: '/user', // 请求的服务器URL
method: 'get', // 请求方法,默认为'get'
baseURL: 'https://api.example.com', // 基础URL
headers: { 'X-Requested-With': 'XMLHttpRequest' }, // 请求头
params: { ID: 12345 }, // URL查询参数
data: { firstName: 'Fred' }, // 请求体数据
timeout: 1000, // 请求超时时间(毫秒)
responseType: 'json', // 响应数据类型
maxRedirects: 5, // 最大重定向次数
withCredentials: false, // 是否携带cookie
};
三、Axios基本用法
3.1 常用请求方法
Axios 为所有 HTTP 请求方法都提供了别名:
// GET请求
axios.get('/user?ID=12345')
.then(response => console.log(response))
.catch(error => console.error(error));
// 带参数的GET请求
axios.get('/user', {
params: {
ID: 12345
}
});
// POST请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
});
// PUT请求
axios.put('/user/12345', {
firstName: 'Fred',
lastName: 'Flintstone'
});
// DELETE请求
axios.delete('/user/12345');
// PATCH请求
axios.patch('/user/12345', {
firstName: 'Fred'
});
3.2 使用 async/await 语法
现代 JavaScript 推荐使用 async/await 语法,代码更简洁易读:
export default {
setup() {
const fetchUser = async (userId) => {
try {
const response = await axios.get(`/users/${userId}`);
console.log('用户数据:', response.data);
return response.data;
} catch (error) {
console.error('获取用户数据失败:', error);
throw error;
}
};
return { fetchUser };
}
};
3.3 响应数据结构
Axios 的响应对象包含以下属性:
{
data: {}, // 服务器返回的响应数据
status: 200, // HTTP状态码
statusText: 'OK', // HTTP状态消息
headers: {}, // 响应头
config: {}, // 请求配置对象
request: {} // 原始请求对象
}
3.4 Vue3 组件中的实际应用
下面是一个完整的 Vue3 组件示例,展示如何使用 Axios 获取和展示数据:
<template>
<div class="user-profile">
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="error" class="error">{{ error }}</div>
<div v-else-if="user" class="profile">
<h2>{{ user.name }}</h2>
<p>邮箱: {{ user.email }}</p>
<p>电话: {{ user.phone }}</p>
</div>
<button @click="fetchUserData">获取用户数据</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const user = ref(null);
const loading = ref(false);
const error = ref(null);
const fetchUserData = async () => {
loading.value = true;
error.value = null;
try {
const response = await axios.get('https://jsonplaceholder.typicode.com/users/1');
user.value = response.data;
} catch (err) {
error.value = '获取用户数据失败,请稍后重试';
console.error('请求失败:', err);
} finally {
loading.value = false;
}
};
</script>
<style scoped>
.user-profile {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.loading, .error {
padding: 20px;
text-align: center;
color: #666;
}
.error {
color: #ff4444;
}
.profile {
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
}
button {
margin-top: 20px;
padding: 10px 20px;
background: #42b983;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #369870;
}
</style>
四、Axios 进阶应用
4.1 Axios 实例创建与管理
在大型项目中,通常需要与多个后端服务交互,此时创建多个 Axios 实例是最佳实践
创建多个实例:
// src/utils/api/postService.js
import axios from 'axios';
export const postService = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com/posts',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
});
// src/utils/api/userService.js
import axios from 'axios';
export const userService = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com/users',
timeout: 5000,
headers: {
'Content-Type': 'application/json'
}
});
配置优先级:Axios 的配置有三个层级,优先级从高到低:
① 请求时配置:只对当前请求有效
② 实例配置:对该实例的所有请求有效
③ 全局配置:对所有请求有效
// 全局配置
axios.defaults.baseURL = 'https://api.example.com';
// 实例配置
const service = axios.create({
baseURL: 'https://api.service.com'
});
// 请求时配置
service.get('/data', {
timeout: 1000
});
4.2 拦截器:请求与响应的统一处理
拦截器是 Axios 最强大的功能之一,允许你在请求发送前和响应返回后进行统一处理
请求拦截器
常用于添加认证 token、显示 loading 状态等:
// src/utils/request.js
import axios from 'axios';
const service = axios.create({
baseURL: 'https://jsonplaceholder.typicode.com',
timeout: 5000
});
// 请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
// 显示loading
store.commit('showLoading');
return config;
},
(error) => {
// 对请求错误做些什么
store.commit('hideLoading');
return Promise.reject(error);
}
);
响应拦截器
常用于统一错误处理、数据格式化等:
// 响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
store.commit('hideLoading');
// 简化数据层级,直接返回data
return response.data;
},
(error) => {
// 对响应错误做点什么
store.commit('hideLoading');
// 统一错误处理
if (error.response) {
switch (error.response.status) {
case 401:
// 未授权,跳转到登录页
router.push('/login');
break;
case 404:
console.error('请求的资源不存在');
break;
case 500:
console.error('服务器内部错误');
break;
default:
console.error('请求失败:', error.response.data);
}
} else if (error.request) {
console.error('网络连接失败');
}
return Promise.reject(error);
}
);
export default service;
4.3 错误处理最佳实践
常见错误类型
const fetchData = async () => {
try {
const response = await service.get('/data');
return response;
} catch (error) {
if (error.response) {
// 请求已发出,服务器返回状态码不在2xx范围内
console.log('响应错误:', error.response.data);
console.log('状态码:', error.response.status);
console.log('响应头:', error.response.headers);
} else if (error.request) {
// 请求已发出,但没有收到响应
console.log('请求错误:', error.request);
} else {
// 请求配置发生错误
console.log('配置错误:', error.message);
}
console.log('请求配置:', error.config);
throw error;
}
};
Axios 支持取消正在进行的请求:
import { ref } from 'vue';
import axios from 'axios';
export default {
setup() {
const cancelTokenSource = ref(null);
const fetchData = async () => {
// 取消之前的请求(如果存在)
if (cancelTokenSource.value) {
cancelTokenSource.value.cancel('请求已取消');
}
cancelTokenSource.value = axios.CancelToken.source();
try {
const response = await axios.get('/data', {
cancelToken: cancelTokenSource.value.token
});
return response.data;
} catch (error) {
if (axios.isCancel(error)) {
console.log('请求被取消:', error.message);
} else {
console.error('请求失败:', error);
}
}
};
const cancelRequest = () => {
if (cancelTokenSource.value) {
cancelTokenSource.value.cancel('用户主动取消请求');
}
};
return { fetchData, cancelRequest };
}
};
4.4 并发请求处理
当需要同时发起多个请求时,使用并发请求可以显著提升性能
使用 Promise.all
const fetchMultipleData = async () => {
try {
const [users, posts, comments] = await Promise.all([
axios.get('/users'),
axios.get('/posts'),
axios.get('/comments')
]);
console.log('用户数据:', users.data);
console.log('文章数据:', posts.data);
console.log('评论数据:', comments.data);
return { users: users.data, posts: posts.data, comments: comments.data };
} catch (error) {
console.error('并发请求失败:', error);
throw error;
}
};
使用 axios.all 和 axios.spread
const fetchMultipleData = () => {
return axios.all([
axios.get('/users'),
axios.get('/posts')
])
.then(axios.spread((usersResponse, postsResponse) => {
return {
users: usersResponse.data,
posts: postsResponse.data
};
}))
.catch(error => {
console.error('并发请求失败:', error);
throw error;
});
};


2917

被折叠的 条评论
为什么被折叠?



