← 目录从零开始学vue3

数据请求(Axios 与 Vue)

2024/9/17

在 Vue 3 setup 下使用 axios 时,可以将 axios 独立于 Vue 组件,放置在单独的文件或目录中,统一处理 API 请求。这样可以提高代码的可维护性和复用性。接下来,我们将详细介绍如何将 axios 独立出来进行全局配置、请求拦截器和响应拦截器的使用、同步与异步请求的处理,以及如何进行全局异常捕捉和处理。

一、项目结构

首先,我们为 axios 创建一个独立的文件夹,将 axios 的配置和 API 请求逻辑封装起来:

text
├── src
│   ├── api
│   │   ├── axiosConfig.js   # axios配置文件
│   │   ├── userApi.js       # 用户相关API请求
│   │   ├── postApi.js       # 文章相关API请求
│   ├── components
│   ├── views
│   ├── App.vue
│   └── main.js

二、axiosConfig.js:axios 全局配置与拦截器

首先,我们在 api/axiosConfig.js 中统一配置 axios。这包括设置基础 URL、超时、请求拦截器、响应拦截器以及全局异常处理。

js
// api/axiosConfig.js
import axios from 'axios';

// 创建 axios 实例
const service = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com', // 基础URL
  timeout: 10000, // 请求超时时间
});

// 请求拦截器
service.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);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 对响应数据做一些处理
    return response.data;
  },
  (error) => {
    // 统一的错误处理
    if (error.response) {
      switch (error.response.status) {
        case 401:
          alert('未授权,请登录');
          window.location.href = '/login'; // 跳转到登录页面
          break;
        case 404:
          alert('请求地址未找到');
          break;
        case 500:
          alert('服务器错误,请稍后重试');
          break;
        default:
          alert(`发生错误:${error.message}`);
      }
    }
    return Promise.reject(error);
  }
);

export default service;

三、封装 API 请求

我们可以在 api/ 目录下创建多个文件来处理不同模块的 API 请求,示例如下:

1. 用户相关 API (userApi.js)

js
// api/userApi.js
import axios from './axiosConfig';

// 获取用户列表
export function getUsers() {
  return axios.get('/users');
}

// 获取单个用户
export function getUserById(id) {
  return axios.get(`/users/${id}`);
}

2. 文章相关 API (postApi.js)

js
// api/postApi.js
import axios from './axiosConfig';

// 获取文章列表
export function getPosts() {
  return axios.get('/posts');
}

// 获取单篇文章
export function getPostById(id) {
  return axios.get(`/posts/${id}`);
}

四、在组件中使用封装的 API

接下来,我们在 Vue 组件中使用这些封装好的 API。以用户数据的展示为例:

vue
<template>
  <div>
    <h1>用户列表</h1>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
    <p v-if="error">{{ error }}</p>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';
import { getUsers } from '../api/userApi'; // 导入封装的API

export default {
  setup() {
    const users = ref([]);
    const error = ref(null);

    // 在组件挂载时调用 API 获取用户列表
    onMounted(async () => {
      try {
        users.value = await getUsers();
      } catch (err) {
        error.value = '获取用户列表失败';
        console.error(err);
      }
    });

    return { users, error };
  }
};
</script>

五、同步与异步请求的处理

axios 默认是异步的,我们可以通过 async/await 来处理异步请求,也可以在需要时处理同步请求。

1. 异步请求

异步请求使用 async/await 处理,代码更加简洁。

js
async function fetchData() {
  try {
    const response = await axios.get('/data');
    console.log('数据:', response);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

2. 同步请求

虽然 axios 本质上是异步的,但我们可以通过 async/await 实现同步请求的效果,即等待请求完成后再执行后续操作:

js
async function fetchDataSync() {
  try {
    const response = await axios.get('/data');
    console.log('同步数据:', response);
  } catch (error) {
    console.error('请求失败:', error);
  }
}

六、全局异常捕捉与处理

为了在全局范围内捕捉异常,我们已经在 axiosConfig.js 中通过响应拦截器统一处理了错误。例如,遇到 401 未授权错误时,自动跳转到登录页面。

可以在具体 API 请求的调用处进一步处理异常,确保所有请求的错误都能得到合适的处理:

js
async function fetchData() {
  try {
    const response = await getPosts();
    console.log('文章数据:', response);
  } catch (error) {
    console.error('获取文章数据失败:', error);
    // 可以根据具体错误类型弹出不同提示
    alert('获取数据失败,请稍后重试');
  }
}

七、总结

  • 全局配置:将 axios 的基础配置和拦截器统一放在 axiosConfig.js 中,便于管理和维护。
  • 拦截器:请求拦截器可用于添加 Token 等信息,响应拦截器可用于处理统一的错误逻辑。
  • API 模块化:将不同业务逻辑的 API 封装在不同的文件中,提高代码的可读性和复用性。
  • 同步与异步:通过 async/await 简化异步请求的代码结构。
  • 全局异常捕捉:通过拦截器统一处理响应错误,确保异常不会导致应用崩溃。

这种将 axios 独立封装的方式不仅可以提高代码复用性,还能方便对请求进行全局化管理,有助于大型项目的开发。