vue3 效率提升神器,howuse/axios 入坑指南

howusevue3
2023-12-23 17:07:52

在项目当中大量使用axios,我一般会创建一个request.js文件。接着在项目src文件夹下面创建api文件夹。大致的代码如下。

js 复制代码
// 封装
const service = axios.create({
  baseURL: '/',
  headers: {
  }
})

// api 文件定义
export const xxxType = (params: any) =>
    service({
        url: "/xxx/types",
        method: "get",
        params,
    });

// 使用
xxxType({ dimension }).then(({data})=>{
      tableLists.value = data?.data || []
})

上面三层架构在项目当中屡试不爽,尤其在大型项目当中,维护起来不要太方便。但是事情远远不是想想的那么简单,有一天测试给我说,你这代码有个bug,这个按钮如果迅速点击,会不停的掉接口。啊?能用就行了,你管这干啥。
事情不光如此简单,有个页面有几个数据巨多的接口,本来后端反应就慢,页面反应也慢,当不停的切换页面的时候,接口疯狂跑向后台,一会儿服务端产生大量的计算。后端同学说:能不能在页面离开的时候中断这个请求呢?long long ago, 前后端不分离的时候也没见酱紫呀。

要命的是,目前项目开始使用vue3框架,这个框架setup的使用方法很好用,可以减少不少的代码。别人都各种use简化代码的时候,我这里还沉沦在Promise的回调地狱当中。

直到遇见howuse/axios,作者的文档少啊,让我走了不少坑。这里认真总结下。

开始入坑 howuse/axios

简介

安装howuse npm i howuse
安装axios npm i axios
github 地址:https://github.com/biancangming/howuse

复制代码
相对于原生axios解决问题:

1. 加入节流自动过滤多余的重复请求,节省带宽同时,一定程度防止表单短时间重复提交的问题

2. vue页面销毁自动取消未完成的请求,节省页面资源

3. 在有必要的情况下,可手动终止当前请求

4. 响应式用法

5. 响应默认值设置

6. 增加path传参模式

先创建个实例,拦截器

ts 复制代码
import { createAxios, type HowAxiosRequestConfig, type HowExRequestOptions } from "howuse/axios"
import { AUTHORIZATION } from './const';

// createAxios 相当于 axios.create,参数完全保持一直, server 相当于 axios.create 的返回值
// 这里很明显,作者没有进行多余的装饰,只是额外封装了 useAxiosRequest 和 useBlobDownload 两个方法
export const { useAxiosRequest, useBlobDownload, server } = createAxios({
  baseURL: "/",
  timeout: 0
});

// 拦截器的创建和原生一模一样
// 请求拦截器
server.interceptors.request.use(
  config => {
    const token = sessionStorage.getItem(AUTHORIZATION)
    if (!token) {
      console.warn("token获取失败...")
    }

    // 设置请求头
    if (config.headers) {
      config.headers[AUTHORIZATION] = `Bearer ${token}`
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  });

// 响应拦截器 适合做一些不影响数据结构的操作,例如token失效返回登录页面等
server.interceptors.response.use(
  (response) => {
    if(response.data?.code === 1 && response.data?.msg) {
      ElMessage.error(response.data.msg);
    }
    // return response.data
    // 网上许多示例将此处直接设置为 response.data ,一定程度上影响未来响应头的获取,一旦需要使用响应头时,变得异常困难
    // 正确的方式应该是将响应的server二次封装
    return response
  },
  (error) => {
    const status = error?.response?.status
    if (status === 401) {
      sessionStorage.clear()
      localStorage.clear()
      // 跳转到登录页面 ...
    } else {
      ElMessage.error(error.response.data.msg || httpStatus[error.response.status]);
    }
    return Promise.reject(error);
  }
)

Api封装

typescript 复制代码
// 这里定义了后端常用的接口形式
// T 根据自己的业务传入
export interface DefResult<T> {
  msg: string,
  data: T,
  code: 0 | 1
}

// 假如我的数据如下
interface IData {
  title: string,
  value: string,
}

// 我在页面使用如下
const { response, data, error, edata,  execute, aborted, abort, finished, loading } = useAxiosRequest<DefResult<IData>>(config, options);

这里的参数和返回值咋一看挺复杂,不过使用多了,爱不释手。继续往下看

我这里举一些例子:

一个简单的GET 请求

api 文件

复制代码
// 根据ColumnId 查询列表,主要用于栏目排序。这里有一个参数在路径上
export function useArticleListByColumnIdRequset() {
  return useDefAxiosRequest<IArticle[]>({ url: "/article/admin-list/{columnId}" })
  // 如果是POST
  // return useDefAxiosRequest<IArticle[]>({ url: "/article/admin-list/{columnId}", method: "POST" })
}

页面当中

typescript 复制代码
const { execute: articleListByColumnIdexecute, data: articleListByColumnIData , abort } = useArticleListByColumnIdRequset()

articleListByColumnIdexecute({ path: { columnId } }) // 路径参数,当然也可以使用 params 和 data

// 假如需要对返回数据二次加工可以直接这样子
const dataSource = computed(() => unref(articleListByColumnIData).data || [])

// 如果想要在请求完成后做一些事情,可以直接.then
articleListByColumnIdexecute({ path: { columnId } }).then(res=>{
   responseMsg(res)
})

// 页面离开中断请求
onUnmounted(() => {
    abort()
})

这里的 articleListByColumnIData 返回是一个ref值,可以查询之后 直接绑定到页面上了。

useAxiosRequest 参数说明

  1. config 类型 HowAxiosRequestConfig 在 AxiosRequestConfig 基础上扩展,完全兼容。

和axios完全保持一直,增加path参数,参阅官网
https://axios-http.com/docs/req_config

  1. options 类型 HowExRequestOptions
参数 类型 描述
immediate boolean 默认 false, 是否在页面加载时,立即执行
delay number 默认 500, 接口防抖延迟时间
isDebounce boolean 默认 true, 是否开启接口防抖
defaultVal any 默认 undefined, 接口返回时的默认值
  1. 响应

  2. response,响应实体

  3. data, 响应实体数据

  4. error,错误信息

  5. edata,错误信息实体数据

  6. execute, 执行调用接口

  7. aborted, 接口是否被取消

  8. abort, 取消接口

  9. finished, 接口请求是否完成

  10. loading,接口是否正在加载中...