深入剖析Vue3中Axios的实战应用与最佳实践

引言:为什么选择Axios?

在 Vue3 项目开发中,数据请求是一个常见的需求。虽然浏览器本身提供了 fetch API,但 Axios 由于其强大的功能,比如拦截器、自动 JSON 转换、请求取消等,成为了大多数 Vue 开发者的首选工具。本文将讲解如何在 Vue3 中高效使用 Axios。

一、项目初始化与基础配置

1.1 安装与引入

npm install axios

yarn add axios

1.2 创建Axios实例

utils/request.js

javascript 复制代码
import axios from 'axios';

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL, // 从环境变量读取
  timeout: 15000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
});

export default service;

1.3 全局挂载(可选)

main.js

javascript 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import axios from './utils/request';

const app = createApp(App);

// 全局挂载
app.config.globalProperties.$axios = axios;

app.mount('#app');

二、核心功能实现

2.1 请求拦截器:统一处理请求

使用请求拦截器来进行一些统一的操作,比如添加 Token 或显示 loading:

javascript 复制代码
service.interceptors.request.use(config => {
  const token = localStorage.getItem('token');
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }
  if (config.method === 'get') {
    config.params = {
      ...config.params,
      _t: Date.now()  // 防止缓存
    };
  }
  if (config.showLoading !== false) {
    showLoading();  // 显示 loading
  }
  return config;
}, error => Promise.reject(error));

2.2 响应拦截器:统一处理响应

响应拦截器可以统一处理成功或失败的请求结果:

javascript 复制代码
service.interceptors.response.use(response => {
  hideLoading();  // 隐藏 loading
  const res = response.data;
  if (res.code === 200) {
    return res.data;  // 返回数据
  } else {
    handleBusinessError(res.code, res.message);
    return Promise.reject(new Error(res.message || 'Error'));
  }
}, error => {
  hideLoading();  // 隐藏 loading
  handleError(error);  // 处理错误
  return Promise.reject(error);
});

三、封装高级请求函数

3.1 通用请求方法封装

封装一个通用的请求函数,支持各种请求方式:

javascript 复制代码
import service from '../utils/request';

export function request(options) {
  return new Promise((resolve, reject) => {
    service(options)
      .then(response => resolve(response))
      .catch(error => reject(error));
  });
}

export function get(url, params = {}, config = {}) {
  return request({
    url,
    method: 'GET',
    params,
    ...config
  });
}

export function post(url, data = {}, config = {}) {
  return request({
    url,
    method: 'POST',
    data,
    ...config
  });
}

3.2 业务API模块化

通过模块化管理 API,例如用户相关接口:

javascript 复制代码
import { get, post } from './http';

export const userApi = {
  login(data) {
    return post('/user/login', data);
  },
  getUserInfo(params) {
    return get('/user/info', params);
  },
  updateUserInfo(data) {
    return post('/user/update', data);
  },
  deleteUser(id) {
    return post(`/user/${id}/delete`);
  }
};

四、在Vue3组件中使用

4.1 Composition API 方式

使用 Composition API 获取并展示数据:

javascript 复制代码
<template>
  <div>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }} - {{ user.email }}</li>
    </ul>
    <button @click="loadUsers" :disabled="loading">{{ loading ? '加载中...' : '加载用户' }}</button>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { userApi } from '../api/user';

const users = ref([]);
const loading = ref(false);
const error = ref(null);

const loadUsers = async () => {
  try {
    loading.value = true;
    const response = await userApi.getUserList({ page: 1, size: 10 });
    users.value = response.list;
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

onMounted(loadUsers);
</script>

4.2 Options API 方式

如果使用 Options API,代码会类似这样:

javascript 复制代码
<script>
import { userApi } from '../api/user';

export default {
  name: 'UserComponent',
  data() {
    return {
      users: [],
      loading: false,
      error: null
    };
  },
  mounted() {
    this.loadUsers();
  },
  methods: {
    async loadUsers() {
      try {
        this.loading = true;
        const response = await userApi.getUserList({ page: 1, size: 10 });
        this.users = response.list;
      } catch (error) {
        this.error = error.message;
      } finally {
        this.loading = false;
      }
    }
  }
};
</script>

五、高级特性应用

5.1 请求取消功能

Axios 支持取消请求。可以通过 CancelToken 来中止请求:

javascript 复制代码
import axios from 'axios';
const CancelToken = axios.CancelToken;
let cancel;

function searchUsers(keyword) {
  if (cancel) {
    cancel('取消上一个请求');
  }
  return userApi.getUserList({ keyword, page: 1, size: 10 }, {
    cancelToken: new CancelToken(c => cancel = c)
  });
}

5.2 请求重试机制

封装带重试机制的请求,适用于网络错误或服务器错误:

javascript 复制代码
export function requestWithRetry(config, maxRetries = 3) {
  return new Promise((resolve, reject) => {
    const attempt = (retryCount) => {
      service(config)
        .then(resolve)
        .catch(error => {
          if (retryCount < maxRetries && shouldRetry(error)) {
            setTimeout(() => attempt(retryCount + 1), 1000 * Math.pow(2, retryCount));  // 指数退避
          } else {
            reject(error);
          }
        });
    };
    attempt(0);
  });
}

function shouldRetry(error) {
  return !error.response || error.response.status >= 500;
}

六、TypeScript支持

6.1 类型定义

在 TypeScript 中可以使用类型定义来确保请求数据的一致性:

TypeScript 复制代码
export interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
}

export interface PageParams {
  page: number;
  size: number;
  keyword?: string;
}

6.2 类型安全的请求封装

为请求函数添加类型支持,提高开发时的类型安全:

TypeScript 复制代码
export async function typedRequest<T = any>(
  config: AxiosRequestConfig
): Promise<T> {
  const response: AxiosResponse<ApiResponse<T>> = await service(config);
  return response.data.data;
}

七、总结

通过合理封装和配置 Axios,不仅可以轻松地进行 HTTP 请求,还能利用拦截器、请求取消和重试机制等高级功能,提高项目的稳定性和用户体验。

相关推荐
冬男zdn1 小时前
优雅的React表单状态管理
前端·javascript·react.js
国服第二切图仔1 小时前
基于Electron for 鸿蒙PC的高性能表格组件封装
javascript·electron·harmonyos·鸿蒙pc
爱加糖的橙子1 小时前
升级到dify1.10.1-fix版本后,还是有漏洞,React和Next.js的版本和官网描述不一样
前端·人工智能·react.js·阿里云
IT·小灰灰1 小时前
Doubao-Seedream-4.5:当AI学会“版式设计思维“——设计师的七种新武器
javascript·网络·人工智能·python·深度学习·生成对抗网络·云计算
柠檬水不加冰_1 小时前
Angular学习记录
javascript·学习·angular.js
黛色正浓1 小时前
【React基础】篇章3:性能优化相关API&&编写类组件Class API&&zustand状态管理
javascript·react.js·ecmascript
2401_860494701 小时前
在React Native鸿蒙跨平台开发中实现一个桶排序算法,如何使用任何排序算法对每个桶中的元素进行排序,再将所有桶中的元素合并成一个有序数组
javascript·react native·react.js·ecmascript·排序算法·harmonyos
我爱学习_zwj1 小时前
Node.js:从浏览器到服务器的JS革命
javascript·node
一字白首1 小时前
Vue 进阶,组件三大组成 + 通信 + 进阶语法
前端·javascript·vue.js