当前位置: 首页 > article >正文

Vue3 中 Axios 深度整合指南:从基础到高级实践引言

在现代前端开发中,与后端API的交互是构建动态应用的核心环节。Axios作为最流行的HTTP客户端之一,以其简洁的API和强大的功能在前端生态中占据重要地位。本文将全面探讨如何在Vue3项目中高效整合Axios,从基础配置到高级封装,从性能优化到安全实践,帮助开发者构建健壮的前后端交互层。

一、Axios基础与Vue3集成

1.1 Axios核心优势

  • 基于Promise:支持异步/await语法

  • 浏览器和Node.js通用:同构应用开发

  • 请求/响应拦截:全局处理逻辑

  • 自动转换JSON:简化数据处理

  • 取消请求:优化用户体验

  • CSRF/XSRF防护:内置安全特性

1.2 安装与基础使用

npm install axios
# 或
yarn add axios

基础示例:

import axios from 'axios';// GET请求
axios.get('/api/user/123').then(response => console.log(response.data)).catch(error => console.error(error));// POST请求
axios.post('/api/user', { name: '张三' }).then(response => console.log('创建成功'));

1.3 Vue3中的集成方式

全局挂载(不推荐)
// main.js
import { createApp } from 'vue';
import axios from 'axios';const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.mount('#app');// 组件中使用
export default {mounted() {this.$axios.get('/api/data');}
}

组合式API推荐方式

// src/utils/http.js
import axios from 'axios';const instance = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 10000
});export default instance;// 组件中使用
import http from '@/utils/http';export default {setup() {const fetchData = async () => {try {const { data } = await http.get('/endpoint');console.log(data);} catch (error) {console.error('请求失败:', error);}};return { fetchData };}
}

二、高级配置与封装
2.1 创建可配置的Axios实例

// src/utils/http.js
import axios from 'axios';
import { ElMessage } from 'element-plus'; // 示例使用Element Plus消息组件const http = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 30000,headers: {'Content-Type': 'application/json;charset=UTF-8'}
});// 请求拦截器
http.interceptors.request.use(config => {// 添加认证tokenconst token = localStorage.getItem('auth_token');if (token) {config.headers.Authorization = `Bearer ${token}`;}return config;},error => {return Promise.reject(error);}
);// 响应拦截器
http.interceptors.response.use(response => {// 处理业务逻辑错误if (response.data?.code !== 200) {ElMessage.error(response.data?.message || '业务错误');return Promise.reject(response.data);}return response.data;},error => {// 统一错误处理if (error.response) {switch (error.response.status) {case 401:ElMessage.error('未授权,请重新登录');router.push('/login');break;case 403:ElMessage.error('拒绝访问');break;case 500:ElMessage.error('服务器错误');break;default:ElMessage.error(`请求错误: ${error.message}`);}} else {ElMessage.error('网络错误,请检查连接');}return Promise.reject(error);}
);export default http;

2.2 TypeScript支持

// src/types/api.d.ts
declare module 'axios' {interface AxiosResponse<T = any> {code: number;message: string;data: T;// 其他自定义字段}
}// 封装响应类型
export interface ApiResponse<T> {code: number;message: string;data: T;timestamp: number;
}// 使用示例
interface User {id: number;name: string;email: string;
}export const getUserInfo = (userId: number): Promise<ApiResponse<User>> => {return http.get(`/user/${userId}`);
};

2.3 API模块化组织

src/api/modules/auth.ts    # 认证相关APIuser.ts    # 用户相关APIproduct.ts # 产品相关APIindex.ts     # API聚合导出
// src/api/modules/user.ts
import http from '@/utils/http';
import type { ApiResponse } from '@/types/api';export interface UserProfile {id: number;name: string;avatar: string;// 其他字段
}export const fetchUserProfile = (): Promise<ApiResponse<UserProfile>> => {return http.get('/user/profile');
};export const updateUserProfile = (data: Partial<UserProfile>
): Promise<ApiResponse<UserProfile>> => {return http.patch('/user/profile', data);
};

三、高级特性实战
3.1 取消请求

import axios, { CancelTokenSource } from 'axios';let cancelTokenSource: CancelTokenSource;export const searchProducts = (keyword: string) => {// 取消之前的请求if (cancelTokenSource) {cancelTokenSource.cancel('取消重复请求');}cancelTokenSource = axios.CancelToken.source();return http.get('/products/search', {params: { q: keyword },cancelToken: cancelTokenSource.token});
};// 组件中使用
const search = async () => {try {const { data } = await searchProducts(keyword.value);products.value = data;} catch (error) {if (!axios.isCancel(error)) {console.error('搜索失败:', error);}}
};

3.2 文件上传与进度监控

<template><input type="file" @change="handleFileUpload" /><div v-if="uploadProgress > 0">上传进度: {{ uploadProgress }}%</div>
</template><script setup>
import { ref } from 'vue';
import http from '@/utils/http';const uploadProgress = ref(0);const handleFileUpload = async (event) => {const file = event.target.files[0];if (!file) return;const formData = new FormData();formData.append('file', file);try {const { data } = await http.post('/upload', formData, {headers: {'Content-Type': 'multipart/form-data'},onUploadProgress: (progressEvent) => {if (progressEvent.total) {uploadProgress.value = Math.round((progressEvent.loaded * 100) / progressEvent.total);}}});console.log('上传成功:', data);} catch (error) {console.error('上传失败:', error);} finally {setTimeout(() => {uploadProgress.value = 0;}, 2000);}
};
</script>

3.3 请求重试机制

// src/utils/http-retry.ts
import http from './http';export const httpWithRetry = async (config: any,maxRetries = 3,retryDelay = 1000
) => {let lastError;for (let i = 0; i < maxRetries; i++) {try {const response = await http(config);return response;} catch (error) {lastError = error;// 只对网络错误和5xx错误重试if (!error.response || error.response.status >= 500) {if (i < maxRetries - 1) {await new Promise(resolve => setTimeout(resolve, retryDelay));retryDelay *= 2; // 指数退避}} else {break;}}}throw lastError;
};// 使用示例
import { httpWithRetry } from '@/utils/http-retry';const fetchImportantData = async () => {try {const data = await httpWithRetry({url: '/critical-data',method: 'get'}, 5); // 最多重试5次console.log('获取关键数据成功:', data);} catch (error) {console.error('最终获取失败:', error);}
};

四、性能优化与安全

4.1 请求缓存策略

// src/utils/http-cache.ts
import http from './http';const cache = new Map();export const httpWithCache = async (config: any, cacheKey: string, ttl = 60000) => {const now = Date.now();// 检查缓存if (cache.has(cacheKey)) {const { data, timestamp } = cache.get(cacheKey);if (now - timestamp < ttl) {return data;}}// 发起新请求try {const response = await http(config);cache.set(cacheKey, {data: response,timestamp: now});return response;} catch (error) {// 失败时返回缓存数据(如果有)if (cache.has(cacheKey)) {console.warn('使用缓存数据:', cacheKey);return cache.get(cacheKey).data;}throw error;}
};// 使用示例
const fetchProductList = async () => {return httpWithCache({ url: '/products', method: 'get' },'product-list',300000 // 5分钟缓存);
};

4.2 并发请求优化

// 使用axios.all处理并发请求
const fetchDashboardData = async () => {try {const [userRes, ordersRes, statsRes] = await Promise.all([http.get('/user/profile'),http.get('/orders/latest'),http.get('/dashboard/stats')]);return {user: userRes.data,orders: ordersRes.data,stats: statsRes.data};} catch (error) {console.error('获取仪表盘数据失败:', error);throw error;}
};

4.3 安全最佳实践

6.2 推荐架构

  1. CSRF防护
     

    // Axios全局配置
    http.defaults.xsrfCookieName = 'csrftoken';
    http.defaults.xsrfHeaderName = 'X-CSRFToken';

  2. JWT自动刷新
     

    // 响应拦截器中处理token刷新
    let isRefreshing = false;
    let refreshSubscribers: any[] = [];http.interceptors.response.use(response => response,async error => {const { config, response } = error;if (response.status === 401 && !config._retry) {if (isRefreshing) {return new Promise(resolve => {refreshSubscribers.push((token: string) => {config.headers.Authorization = `Bearer ${token}`;resolve(http(config));});});}config._retry = true;isRefreshing = true;try {const { data } = await http.post('/auth/refresh');localStorage.setItem('auth_token', data.token);// 重试所有挂起的请求refreshSubscribers.forEach(cb => cb(data.token));refreshSubscribers = [];// 重试原始请求config.headers.Authorization = `Bearer ${data.token}`;return http(config);} catch (refreshError) {// 刷新失败,跳转登录localStorage.removeItem('auth_token');router.push('/login');return Promise.reject(refreshError);} finally {isRefreshing = false;}}return Promise.reject(error);}
    );

    五、测试与调试

    5.1 Mock服务配置
     

    // 使用msw(Mock Service Worker)
    // src/mocks/handlers.js
    import { rest } from 'msw';export const handlers = [rest.get('/api/user', (req, res, ctx) => {return res(ctx.delay(150),ctx.json({id: 1,name: 'Mock User'}));}),// 其他mock接口
    ];// src/mocks/browser.js
    import { setupWorker } from 'msw';
    import { handlers } from './handlers';export const worker = setupWorker(...handlers);

    5.2 单元测试示例

    // tests/unit/api.spec.ts
    import axios from 'axios';
    import MockAdapter from 'axios-mock-adapter';
    import { fetchUserProfile } from '@/api/modules/user';describe('User API', () => {let mockAxios: MockAdapter;beforeEach(() => {mockAxios = new MockAdapter(axios);});afterEach(() => {mockAxios.restore();});it('fetchUserProfile returns user data', async () => {const mockData = { id: 1, name: 'Test User' };mockAxios.onGet('/user/profile').reply(200, {code: 200,data: mockData,message: 'success'});const response = await fetchUserProfile();expect(response.data).toEqual(mockData);});it('handles 404 error', async () => {mockAxios.onGet('/user/profile').reply(404);await expect(fetchUserProfile()).rejects.toThrow();});
    });

    六、总结与最佳实践

    6.1 关键点总结

  3. 封装优于直接使用:创建配置好的Axios实例并统一管理

  4. 类型安全:为API响应添加TypeScript类型定义

  5. 模块化组织:按业务领域组织API模块

  6. 错误处理:全局拦截器中统一处理错误

  7. 安全考虑:实现CSRF防护和JWT自动刷新

  8. 性能优化:合理使用缓存、取消重复请求
     

    src/api/modules/       # 按业务模块组织的APItypes/         # 类型定义utils/http.ts      # Axios实例配置interceptors # 拦截器cache.ts     # 缓存策略retry.ts     # 重试机制stores/          # Pinia状态管理modules/       # 与API模块对应的状态模块

相关文章:

Vue3 中 Axios 深度整合指南:从基础到高级实践引言

在现代前端开发中&#xff0c;与后端API的交互是构建动态应用的核心环节。Axios作为最流行的HTTP客户端之一&#xff0c;以其简洁的API和强大的功能在前端生态中占据重要地位。本文将全面探讨如何在Vue3项目中高效整合Axios&#xff0c;从基础配置到高级封装&#xff0c;从性能…...

MySQL#Select语句执行过程

服务端程序架构 MySQL 是典型的 C/S 架构&#xff0c;即 Client/Server 架构&#xff0c;服务器端程序mysqld。 Select语句执行过程 连接层 客户端和服务器端建立连接&#xff0c;客户端发送 SQL 至服务器端 SQL层 SQL语句处理 查询缓存&#xff1a; 缓存命中该SQL执行结果直…...

hbuilder中h5转为小程序提交发布审核

【注意】 [HBuilder] 11:59:15.179 此应用 DCloud appid 为 __UNI__9F9CC77 &#xff0c;您不是这个应用的项目成员。1、联系这个应用的所有者&#xff0c;请求加入项目成员&#xff08;https://dev.dcloud.net.cn "成员管理"-"添加项目成员"&#xff09;…...

文档注释:删还是不删

问题&#xff1a;代码中存在大量的文档注释&#xff0c;占用大量篇幅&#xff0c;一次难以看完整个文件&#xff0c;于是诞生了一个想法&#xff1a;删除所有文档注释&#xff0c;于是问了下 DeepWiki 文档注释对tree - sitter有影响吗&#xff1f;文档注释对Roocode大模型理解…...

【数据结构】单链表练习

1.链表的中间节点 https://leetcode.cn/problems/middle-of-the-linked-list/description/ 用快慢指针来解决 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ struct ListNode* middleNode(struct ListNode* he…...

JVM 性能优化终极指南:全版本兼容、参数公式与场景实战

一、引言 JVM 优化的核心难点在于版本兼容性与场景适配性。从 Java 8 到 Java 21&#xff0c;JVM 的内存模型、GC 策略和默认参数发生了巨大变化&#xff1b;从高并发 Web 到大数据批处理&#xff0c;不同业务场景对延迟、吞吐量的要求也截然不同。本文基于历史会话中用户关注…...

分布式爬虫监控架构设计

1. 监控架构核心组件 1.1 日志集中管理 设计目标&#xff1a;聚合所有节点的运行日志&#xff0c;支持实时查询与异常分析。 实现方式&#xff1a; 日志采集&#xff1a;各节点通过 logging 模块将日志发送至中央存储&#xff08;如Elasticsearch或Redis&#xff09;。 日志…...

MySQL的参数 innodb_force_recovery 详解

MySQL的参数 innodb_force_recovery 详解 innodb_force_recovery 是 InnoDB 存储引擎的一个重要参数&#xff0c;用于在数据库崩溃恢复时控制恢复行为的级别。这个参数主要在数据库无法正常启动时使用&#xff0c;可以帮助我们从损坏的数据库中恢复数据。 一 参数概述 参数名…...

学习vue3:跨组件通信(provide+inject)

目录 一&#xff0c;关于跨组件通信概述 二&#xff0c;跨组件传值 案例1(爷传孙&#xff09; 三&#xff0c;跨组件传函数 案例2(爷传孙&#xff09; 疑问&#xff1a;孙子传给爷爷是否可行呢&#xff1f; 一&#xff0c;关于跨组件通信概述 之前我们学习了父子组件的传…...

Alibaba Sentinel 入门教程:从理论到实战

文章目录 第一部分&#xff1a;理论篇1. Sentinel 简介2. Sentinel 核心原理2.1 资源与规则2.2 Sentinel 工作主流程2.3 核心类解析 3. Sentinel 功能支持与使用流程3.1 流量控制3.2 熔断降级3.3 系统自适应保护3.4 热点参数限流3.5 黑白名单控制3.6 使用流程 4. Sentinel 架构…...

2.3 TypeScript 非空断言操作符(后缀 !)详解

在 TypeScript 中&#xff0c;当你开启了严格的空值检查&#xff08;strictNullChecks&#xff09;后&#xff0c;变量如果可能是 null 或 undefined&#xff0c;就必须在使用前进行显式的判断。为了在某些场景下简化代码&#xff0c;TypeScript 提供了非空断言操作符&#xff…...

【菜狗work前端】小程序加if判断时不及时刷新 vs Web

零、前提&#xff1a; 实现input输入数字不大于10000&#xff08;需要配合typenumber&#xff0c;maxlength5&#xff0c;这里没写&#xff09; 一、探究代码&#xff1a; <input v-model"model1" input"changeModel1" placeholder"请输入拒收件…...

01 NLP的发展历程和挑战

1.人工智能行业介绍 ANI、AGI、ASI 以下是弱人工智能&#xff08;ANI&#xff09;、强人工智能&#xff08;AGI&#xff09;和超强人工智能&#xff08;ASI&#xff09;的对比表格&#xff1a; 类型定义当前状态弱人工智能&#xff08;ANI&#xff09;专注于特定任务&#x…...

TCP 三次握手:详解与原理

无图、长文警告&#xff01;&#xff01;&#xff01;&#xff01; 文章目录 一、引言二、TCP 三次握手的过程&#xff08;一&#xff09;第一次握手&#xff1a;SYN&#xff08;同步序列号&#xff09;&#xff08;二&#xff09;第二次握手&#xff1a;SYN-ACK&#xff08;同…...

LabVIEW累加器标签通道

主要展示了 Accumulator Tag 通道的使用&#xff0c;通过三个并行运行的循环模拟不同数值的多个随机序列&#xff0c;分别以不同频率向累加器写入数值&#xff0c;右侧循环每秒读取累加器值&#xff0c;同时可切换查看每秒内每次事件的平均值&#xff0c;用于演示多线程数据交互…...

在 Unity 中,Start 方法直接设置 RectTransform 的位置,时出现问题,与预计位置不匹配。

改动之前的源代码&#xff1a;发现组件的位置&#xff0c;与设计的位置不一样&#xff0c;但是如果把这段代码&#xff0c;交给一个按钮按下回调&#xff0c;就不会出现问题。 void Start(){//初始化Text 行//读取配置文件&#xff1b;StaticDataObj obj Resources.Load<St…...

永磁同步电机控制算法--IP调节器

一、基本原理 在电机控制领域&#xff0c;现今普遍使用的是比例-积分(PI)控制器。然而&#xff0c;PI控制器有一些缺点&#xff0c;可能会在某些应用中产生一些问题&#xff0c;例如:一个非常快的响应&#xff0c;也同时具有过大的超调量。虽然设计PI控制器时&#xff0c;可以…...

Ubuntu 25.04 锁屏不能远程连接的解决方案

最近安装了一个 Ubuntu 25.04&#xff0c;偶然发现可以通过 windows 自带的 rdp 远程工具进行连接&#xff0c;内心狂喜。此外&#xff0c;还支持启动 VNC 协议&#xff0c;也就是默认支持了 rdp 和 vnc 连接。 看了以下&#xff0c;ubuntu 在用户级别下创建了一个远程桌面服务…...

Java 自动装箱和拆箱还有包装类的缓存问题

自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。JDK1.5 后&#xff0c; Java 引入了自动装箱(autoboxing)/拆箱(unboxing)。 自动装箱&#xff1a; 基本类型的数据处于需要对象的环境中时&#xff0c;会自动转为“对象”。 我们以 Integer 为例&#xff1a;…...

java-jdk8新特性Stream流

一、Stream流 是专业用于对集合或者数组进行便捷操作的。 1.1 Stream流的创建 主要分为Collection&#xff08;List与Set&#xff09;、Map、数组三种创建方式&#xff1a; //1.Collection集合的创建List<String> names new ArrayList<>();Collections.addAll(…...

大语言模型 21 - MCP 自动操作 Figma+Cursor 实现将原型转换为代码

MCP 基本介绍 官方地址&#xff1a; https://modelcontextprotocol.io/introduction “MCP 是一种开放协议&#xff0c;旨在标准化应用程序向大型语言模型&#xff08;LLM&#xff09;提供上下文的方式。可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 提供了一种…...

QNAP NEXTCLOUD 域名访问

我是用docker compose方式安装的&#xff0c;虽然不知道是不是这么个叫法&#xff0c;废话不多说。 背景&#xff1a;威联通container station安装了nextcloud和lucky&#xff0c;lucky进行的域名解析和反代 先在想安装的路径、数据存储路径、数据库路径等新建文件夹。再新建…...

Spring MVC深度解析:控制器与视图解析及RESTful API设计最佳实践

引言 在现代Java Web开发领域&#xff0c;Spring MVC框架凭借其优雅的设计和强大的功能&#xff0c;已成为构建企业级Web应用的首选框架。本文将深入探讨Spring MVC的核心机制——控制器与视图解析&#xff0c;并详细讲解如何设计符合RESTful风格的API。无论你是刚接触Spring …...

华为OD机试真题——信道分配(2025B卷:200分)Java/python/JavaScript/C/C++/GO最佳实现

2025 B卷 200分 题型 本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式; 并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析; 本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分…...

比亚迪“双剑”电池获中汽中心权威认证,堪称“移动安全堡垒”。

在新能源汽车发展中&#xff0c;电池安全是重中之重。比亚迪的刀片电池与闪充刀片电池提前通过电池新国标全项检测&#xff0c;获中汽中心权威认证&#xff0c;堪称“移动安全堡垒”。 传统电池极端条件下易热失控&#xff0c;而刀片电池独特长条形设计&#xff0c;似刀片般&am…...

【mysql】mysql的高级函数、高级用法

mysql是最常用的数据库之一&#xff0c;常见的函数用法大家应该都很熟悉&#xff0c;本文主要例举一些相对出现频率比较少的高级用法 (注&#xff1a;需注意mysql版本&#xff0c;大部分高级特性都是mysql8才有的) 多值索引与虚拟列 主要是解决字符串索引问题&#xff0c;光说…...

了解一下C#的SortedSet

基础概念 SortedSet 是 C# 中的一个集合类型&#xff0c;位于 System.Collections.Generic 命名空间下。它是一个自动排序的集合&#xff0c;用于存储不重复的元素&#xff0c;并且会根据元素的自然顺序&#xff08;默认排序&#xff09;或自定义比较器进行排序&#xff0c;内…...

【平面波导外腔激光器专题系列】用于光纤传感的低噪声PLC外腔窄线宽激光器

----翻译自Mazin Alalusi等人的文章 摘要 高性价比的 1550 nm DWDM平面外腔 &#xff08;PLANEX&#xff09; 激光器是干涉测量、布里渊、LIDAR 和其他光传感应用的最佳选择。其线宽<3kHz、低相位/频率噪声和极低的RIN。 简介 高性能光纤分布式传感技术是在过去几年中开发…...

Pytorch里面多任务Loss是加起来还是分别backward? | Pytorch | 深度学习

当你在深度学习中进入“多任务学习(Multi-task Learning)”的领域,第一道关卡可能不是设计网络结构,也不是准备数据集,而是:多个Loss到底是加起来一起backward,还是分别backward? 这个问题看似简单,却涉及PyTorch计算图的构建逻辑、自动求导机制、内存管理、任务耦合…...

K8S Pod调度方法实例

以下是一篇面向企业用户、兼具通俗易懂和实战深度的 Kubernetes Pod 调度方法详解博文大纲与正文示例。全文采用“图文&#xff08;代码块&#xff09;并茂 问答穿插 类比”方式&#xff0c;模拟了真实终端操作及输出&#xff0c;便于读者快速上手。 一、引言 为什么要关注 P…...