在 Vue 3 项目中,结合 TypeScript 和 Axios 封装一个通用的 HTTP 请求工具类

1,632 阅读1分钟

在 Vue 3 项目中,结合 TypeScript 和 Axios 封装一个通用的 HTTP 请求工具类,可以提高代码的可维护性和复用性。以下是一个完整的封装示例:

1. 安装 Axios

如果项目中没有安装 Axios,可以通过以下命令安装:

npm install axios

2. 创建 Axios 封装工具类

在 src/utils 目录下创建一个文件 http.ts,用于封装 Axios:

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

// 定义接口返回的数据结构
interface ApiResponse<T = any> {
  code: number;
  message: string;
  data: T;
}

class HttpClient {
  private instance: AxiosInstance;

  constructor(baseURL: string) {
    this.instance = axios.create({
      baseURL,
      timeout: 10000, // 请求超时时间
      headers: {
        'Content-Type': 'application/json',
      },
    });

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 在发送请求之前可以做一些处理,比如添加 token
        const token = localStorage.getItem('token');
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        // 对响应数据做一些处理
        if (response.data.code !== 200) {
          console.error('请求失败:', response.data.message);
          return Promise.reject(response.data.message);
        }
        return response.data.data; // 直接返回实际数据
      },
      (error) => {
        // 对错误响应做一些处理
        console.error('请求出错:', error.message);
        return Promise.reject(error);
      }
    );
  }

  // 封装 GET 请求
  public async get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.get(url, config);
  }

  // 封装 POST 请求
  public async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.post(url, data, config);
  }

  // 封装 PUT 请求
  public async put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.put(url, data, config);
  }

  // 封装 DELETE 请求
  public async delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.instance.delete(url, config);
  }
}

// 创建实例并导出
const baseURL = 'https://api.example.com'; // 替换为你的 API 地址
const http = new HttpClient(baseURL);

export default http;

3. 在组件中使用封装的 Axios

在 Vue 组件中,可以直接导入并使用封装好的 http 工具类:

<template>
  <div>
    <button @click="fetchData">获取数据</button>
    <button @click="submitData">提交数据</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import http from '@/utils/http';

export default defineComponent({
  methods: {
    async fetchData() {
      try {
        const data = await http.get<{ id: number; name: string }>('/api/data');
        console.log('获取到的数据:', data);
      } catch (error) {
        console.error('获取数据失败:', error);
      }
    },
    async submitData() {
      try {
        const response = await http.post('/api/submit', { name: 'John', age: 25 });
        console.log('提交成功:', response);
      } catch (error) {
        console.error('提交失败:', error);
      }
    },
  },
});
</script>

4. 全局挂载 Axios 实例(可选)

如果你希望在整个项目中更方便地使用封装的 Axios 实例,可以将其挂载到 Vue 的全局属性上。

在 src/main.ts 中:

import { createApp } from 'vue';
import App from './App.vue';
import http from './utils/http';

const app = createApp(App);

// 挂载到全局属性
app.config.globalProperties.$http = http;

app.mount('#app');

在组件中使用:

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  methods: {
    async fetchData() {
      try {
        const data = await this.$http.get('/api/data');
        console.log('获取到的数据:', data);
      } catch (error) {
        console.error('获取数据失败:', error);
      }
    },
  },
});
</script>

5. 添加类型支持(可选)

为了更好的 TypeScript 支持,可以在 src/types 目录下定义全局类型:

// src/types/http.d.ts
import { ComponentCustomProperties } from 'vue';
import HttpClient from '@/utils/http';

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $http: HttpClient;
  }
}

6. 总结

通过以上步骤,我们实现了一个基于 Vue 3 和 TypeScript 的 Axios 封装工具类。它具有以下特点:

  • 支持请求和响应拦截器。
  • 提供了 GET、POST、PUT、DELETE 等常用方法的封装。
  • 支持 TypeScript 类型推断,提高代码的健壮性。
  • 可以全局挂载,方便在项目中复用。

你可以根据项目需求进一步扩展和优化这个封装工具类,例如添加文件上传、下载等功能。