程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

  • Vue3

  • vue3 + TS 项目集成

    • 集成element-plus
    • 项目配置 src 别名
    • 项目配置环境变量
    • 项目集成 SVG 图标
    • 项目集成 SASS(SCSS)
    • 项目集成 Mock 数据
    • 项目集成axios二次封装
      • 1. 安装 `axios`
      • 2. 创建 `utils/request.ts`
      • 3. 统一 API 配置
        • 全局 `baseURL` 设置
      • 4. 请求拦截器:自动携带 `token`
      • 5. 响应拦截器:自动处理 API 响应
      • 6. 处理 HTTP 网络错误
      • 7. 如何使用封装后的 `axios`
        • 发送 `GET` 请求
        • 发送 `POST` 请求
        • 发送 `DELETE` 请求
      • 8. 进一步优化
    • 项目集成 vite调试工具
    • 项目集成自动注册组件
    • 项目集成自动导入 API
  • Vue全家桶
  • vue3 + TS 项目集成
scholar
2025-04-30
目录

项目集成axios二次封装

# 项目集成axios二次封装

在 Vue3 项目开发过程中,我们需要与后端 API 进行交互。为了提高开发效率和代码的可维护性,我们通常会对 axios 进行 二次封装,这样可以:

  • 统一管理 API 配置,避免在多个组件中重复定义 baseURL、超时时间等。
  • 全局处理请求和响应,例如:
    • 请求前:自动携带 token,防止用户未授权访问。
    • 请求后:自动解析数据,统一处理错误信息。
  • 优化用户体验,在网络异常时,及时给出反馈(如 ElMessage 提示)。

# 1. 安装 axios

如果你的项目还没有安装 axios,可以使用以下命令安装:

pnpm install axios
1

或者:

npm install axios
# 或
yarn add axios
1
2
3

# 2. 创建 utils/request.ts

在 src/utils/ 目录下创建 request.ts 文件,我们将在这里对 axios 进行封装,使其更符合项目需求。

import axios from "axios";
import { ElMessage } from "element-plus";

// 创建 axios 实例
const request = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API, // 读取环境变量中的 API 地址
  timeout: 5000, // 超时时间 5s
});

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    // 在请求头中携带 `token`
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    return config;
  },
  (error) => {
    // 请求错误
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  (response) => {
    // 直接返回服务器的数据(去掉 `axios` 自动包裹的一层)
    return response.data;
  },
  (error) => {
    // 处理 HTTP 网络错误
    let msg = "";
    if (error.response) {
      const status = error.response.status;
      switch (status) {
        case 401:
          msg = "Token 过期,请重新登录";
          break;
        case 403:
          msg = "无权限访问";
          break;
        case 404:
          msg = "请求地址不存在";
          break;
        case 500:
          msg = "服务器错误,请稍后再试";
          break;
        default:
          msg = "网络连接失败";
      }
    } else {
      msg = "请求超时,请检查网络";
    }

    // 提示错误信息
    ElMessage.error(msg);
    
    // 返回失败的 `Promise`
    return Promise.reject(error);
  }
);

export default request;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 3. 统一 API 配置

# 全局 baseURL 设置

在 request.ts 文件中,我们使用:

baseURL: import.meta.env.VITE_APP_BASE_API
1

它会从 环境变量 读取 API 地址,支持不同环境(开发、生产)自动切换:

# .env.development
VITE_APP_BASE_API = "http://localhost:3000/api"

# .env.production
VITE_APP_BASE_API = "https://api.example.com"
1
2
3
4
5

这样,在 开发环境 和 生产环境 下,API 地址会自动匹配,无需手动更改。


# 4. 请求拦截器:自动携带 token

request.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem("token");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    return config;
  }
);
1
2
3
4
5
6
7
8
9
10

拦截器作用:

  • 在 每次请求前,自动读取 token 并添加到请求头,确保需要授权的接口能正常访问。
  • 避免手动在每个 API 调用时都要传递 token,减少代码重复。

# 5. 响应拦截器:自动处理 API 响应

request.interceptors.response.use(
  (response) => {
    return response.data; // 直接返回 data,简化数据结构
  }
);
1
2
3
4
5

拦截器作用:

  • 简化 API 数据格式:去掉 axios 默认的 response.data 结构,调用 API 时直接拿到服务器返回的数据。
  • 减少 data.data 嵌套问题,前端不再需要 res.data.data,直接使用 res.data。

# 6. 处理 HTTP 网络错误

request.interceptors.response.use(
  (response) => response.data,
  (error) => {
    let msg = "";
    if (error.response) {
      const status = error.response.status;
      switch (status) {
        case 401:
          msg = "Token 过期,请重新登录";
          break;
        case 403:
          msg = "无权限访问";
          break;
        case 404:
          msg = "请求地址不存在";
          break;
        case 500:
          msg = "服务器错误,请稍后再试";
          break;
        default:
          msg = "网络连接失败";
      }
    } else {
      msg = "请求超时,请检查网络";
    }

    ElMessage.error(msg);
    return Promise.reject(error);
  }
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

拦截器作用:

  • 统一处理 HTTP 状态码错误,如 401、403、404。
  • 使用 ElMessage 进行错误提示,提高用户体验。
  • 确保 .then() 只会在成功时执行,避免错误请求污染逻辑。

# 7. 如何使用封装后的 axios

# 发送 GET 请求

import request from "@/utils/request";

request.get("/user/info").then((res) => {
  console.log("用户信息:", res);
});
1
2
3
4
5

# 发送 POST 请求

request.post("/user/login", {
  username: "admin",
  password: "123456",
}).then((res) => {
  console.log("登录成功:", res);
});
1
2
3
4
5
6

# 发送 DELETE 请求

request.delete("/user/delete", { data: { userId: 1 } }).then((res) => {
  console.log("删除用户:", res);
});
1
2
3

# 8. 进一步优化

统一 API 返回数据格式

如果后端返回的数据结构不统一,可以在 request.ts 中统一格式化:

request.interceptors.response.use((response) => {
  const res = response.data;
  if (res.code !== 200) {
    ElMessage.error(res.message || "请求失败");
    return Promise.reject(res.message);
  }
  return res.data; // 只返回 data 字段,简化数据结构
});
1
2
3
4
5
6
7
8

这样,前端调用 API 时不需要额外解析 data:

request.get("/user/info").then((userInfo) => {
  console.log("用户信息:", userInfo);
});
1
2
3
编辑此页 (opens new window)
项目集成 Mock 数据
项目集成 vite调试工具

← 项目集成 Mock 数据 项目集成 vite调试工具→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式