typescript简单封装axios

前言

最近在学习vue3和typescript,在用到axios的时候遇到了一点问题。之前vue2项目中是简单封装过axios,配置和使用比直接用会方便一些。到了vue3+ts项目中,我也直接将封装文件拿来用,也确实能用。但是axios返回的值的类型与我预期的大不相同,导致我想获取接口返回的数据就会报ts错误,错误提示返回值上不存在"xxx"属性。这是因为返回值类型没有定义,其实这个类型错误并不影响js运行,一样可以拿到接口返回值并使用,但是我不能接受。查找了很多文章,有些可能是代码没贴全导致报了更多的错,有些则是封装的过于抽象无法理解导致我望而却步,最后我还是找到了我需要的。

代码

首先感谢大佬的文章,原文链接,提供的代码确实是开箱即用,我这里根据自己的业务做了点微调,axios.ts代码:

// axios.ts
import axios, {
    
     AxiosInstance, AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import {
    
     Dialog } from 'vant'
// 数据返回的接口
// 定义请求响应参数,不含data
interface Result {
    
    
  code: number;
  msg: string
}

// 请求响应参数,包含data
interface ResultData<T = any> extends Result {
    
    
  data?: T;
}
const URL: string = '你的项目url'
enum RequestEnums {
    
    
  TIMEOUT = 20000,
  SUCCESS = 200, // 请求成功
}
const config = {
    
    
  // 默认地址
  baseURL: URL,
  // 设置超时时间
  timeout: RequestEnums.TIMEOUT,
  // 跨域时候允许携带凭证
  // withCredentials: true
}

class RequestHttp {
    
    
  // 定义成员变量并指定类型
  service: AxiosInstance;
  public constructor(config: AxiosRequestConfig) {
    
    
    // 实例化axios
    this.service = axios.create(config);

    /**
     * 请求拦截器
     * 客户端发送请求 -> [请求拦截器] -> 服务器
     * token校验(JWT) : 接受服务器返回的token,存储到vuex/pinia/本地储存当中
     */
    this.service.interceptors.request.use(
      (config: AxiosRequestConfig) => {
    
    
        // const token = localStorage.getItem('token') || '';
        return {
    
    
          ...config,
          // headers: {
    
    
          //   'x-access-token': token, // 请求头中携带token信息
          // }
        }
      },
      (error: AxiosError) => {
    
    
        // 请求报错
        Promise.reject(error)
      }
    )

    /**
     * 响应拦截器
     * 服务器返回信息 -> [响应拦截器] -> 客户端JS获取到信息
     */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => {
    
    
        const {
    
     data } = response
        // 全局错误信息拦截
        if (data.code && data.code !== RequestEnums.SUCCESS) {
    
    
          Dialog.alert({
    
    
            title: '提示',
            message: data.msg || '请求出错'
          })
          // return Promise.reject(data)
        }
        return data;
      },
      (error: AxiosError) => {
    
    
        const {
    
     response } = error;
        if (response && response.status !== 200) {
    
    
          Dialog.alert({
    
    
            title: '提示',
            message: '请求失败'
          })
        }
      }
    )
  }

  // 常用方法封装
  get<T>(url: string, params?: object): Promise<ResultData<T>> {
    
    
    return this.service.get(url, {
    
     params });
  }
  post<T>(url: string, params?: object): Promise<ResultData<T>> {
    
    
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<ResultData<T>> {
    
    
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<ResultData<T>> {
    
    
    return this.service.delete(url, {
    
     params });
  }
}

// 导出一个实例对象
export default new RequestHttp(config);

根目录新建types.ts

// types.ts
// 预约
export interface Booking {
    
    
  id: number
  name: string
  phone: string
  posttime: string
}

// 预约请求体
export interface BookingReqForm {
    
    
  name: string
  phone: string
  posttime: string
}

// 预约响应体
export interface BookingResData {
    
    
  id: number
}

apis新建index.ts:

// index.ts
import axios from '@/utils/axios'
import {
    
     Booking, BookingReqForm } from '@/types'

// 获取预约列表
export const getBookingList = () => {
    
    
  return axios.get<Array<Booking>>('/api/getBookingList')
}

// 新增预约
export const addBooking = (data: BookingReqForm) => {
    
    
  return axios.post<BookingResData>('/api/addBooking', data)
}

组件中使用

// BookingList.vue
<script setup lang="ts">
import {
    
     Ref, ref } from 'vue';
import {
    
     getBookingList } from '@/apis/index'
import {
    
     Booking } from '@/types'

// 如果使用reactive,将data赋值给bookingList会失去响应性
const bookingList: Ref<Booking[]> = ref([])
const _getBookingList = async () => {
    
    
  const {
    
     data } = await getBookingList()
  if (data) bookingList.value = data
}
_getBookingList()
</script>

// AddBooking.vue
<script setup lang="ts">
import {
    
     Ref, ref } from 'vue';
import {
    
     useRouter } from 'vue-router'

const name = ref('')
const phone = ref('')
const posttime = ref('')
const router = useRouter()

const onSubmit = async () => {
    
    
  const params = {
    
    
    name: name.value,
    phone: phone.value,
    posttime: posttime.value
  }
  const {
    
     msg } = await addBooking(params)
  Dialog.alert({
    
    
    title: '提示',
    message: msg || '提交成功',
  }).then(() => {
    
    
    // on close
    router.back()
  })
}
</script>

这样ts就不会报属性不存在的错误了

猜你喜欢

转载自blog.csdn.net/sunddy_x/article/details/125282649