使用 Vue3 组合式 API 封装表格请求

1,979 阅读3分钟

最近在阅读 aHooks 文档时,我发现了一个非常实用的函数——useAntdTable,它封装了 Ant Design Table 组件常见的逻辑。刚好最近我自己也封装了一个类似的 Table 组件 x-table,于是我决定尝试封装一个类似的函数。

与 React 的 Hook 类似,Vue3 提供了组合式 API ,它可以帮助我们更方便地封装和复用有状态逻辑。下面我将介绍如何使用 Vue3 的组合式函数来实现一个简单高效的 useTable 函数。

使用

首先,让我们看一下 useTable 是如何使用的。

基础用法

<template>
  <x-table :columns="columns" v-bind="tableProps" >
</template>

<script setup lang='ts'>
  const { tableProps } = useTable(getArticleList)
</script>

简单吗?只要几行代码就能轻松搞定一个报表页面,剩下的时间我们是不是就可以用来愉快的)了。

高级用法

除了基本用法,useTable 函数还提供了其他配置项。

const options = {
  immediate: true, // 默认立即加载数据
  pageable: true, // 是否可分页,默认为true
  pageNum: 1,  // 默认的分页参数
  pageSize: 10, // 默认的分页参数
  onBeforeRequest (params) => {
    console.log("请求前:", params);
    return params
  },
  onSuccess: (data) => {
    console.log("请求成功:", data);
  },
  onError: (error) => {
    console.error("请求失败:", error);
  },
  onFinally: () => {
    console.log("请求结束");
  },
};

const { loading, form, data, total, tableProps, query, reset } = useTable(
  service,
  options
);

设计与实现

类型定义

export default function useTable<
  TService extends UseTableService<any, any>,
  TDataItem extends ExtractServiceDataItem<TService>,
  TParams extends ExtractServiceParams<TService>,
>(
  service: TService,
  defaultParams?: TParams,
  options?: UseTableOptions<TDataItem, ExtractServiceParams<TService>>,
): UseTableReturn<TDataItem, TParams> 

useTable 函数接受两个参数:servicedefaultParamsoptionsservice 是请求方法,而 defaultParamsoptions 是可选参数。

sp20230714_142533_524.png

通过使用泛型参数,我们可以根据传入的 getArticleList 方法来推断出具体的参数和返回值类型。

配置项

interface UseTableOptions<TDataItem, TParams> {
  immediate?: boolean
  pageable?: boolean
  pageSize?: number
  pageNum?: number
  onBeforeRequest?: (params: TParams, paging: PagingRequest) => TParams
  onChange?: (data: XTableChangeData) => void
  onSuccess?: (data: TableServiceResponse<TDataItem>) => void
  onError?: (error: unknown) => void
  onFinally?: () => void
}
  • immediate: 是否立即加载数据
  • pageable: 是否需要分页
  • pageSize: 分页数量
  • pageNum: 当前页
  • onBeforeRequest: 请求前的参数处理
  • onSuccess: 请求成功时的回调
  • onError: 请求失败时的回调
  • onFinally: 请求结束时的回调

返回值

interface UseTableReturn<TDataItem, TParams> {
  query: () => Promise<void>
  reset: () => Promise<void>
  abort: () => void
  loading: Ref<boolean>
  form: Ref<TParams>
  data: Ref<TDataItem[]>
  tableProps: ComputedRef<{
    loading: boolean
    dataSource: TDataItem[]
    pageNum: number
    pageSize: number
    total: number
    pageable: boolean
    onChange: (data: XTableChangeData) => void
  }>
}

函数返回一个包含以下属性的对象:

  • query  获取数据的函数
  • reset  重置表格参数,并重新获取数据
  • abort  取消请求的函数
  • loading: 接口请求状态
  • form: 响应式表单数据
  • data: 接口返回的表格数据
  • tableProps:表格的属性,包括表格数据、分页排序等

tableProps 主要是配合 x-table 使用,提供表格需要的一些属性。

请求方法

const fetchData = async () => {
    try {
      abortController?.abort()
      loading.value = true
      abortController = new AbortController()

      const res = await service(getParams(), {
        signal: abortController.signal,
      })

      if (pageable) {
        const ret = res.data as PagingResult<TDataItem[]>
        data.value = ret.list
        total.value = ret.count
      } else {
        const ret = res.data as TDataItem[]
        data.value = ret
        total.value = ret.length
      }

      onSuccess?.(res)
    } catch (error) {
      if (!(error instanceof DOMException && error.name === 'AbortError')) {
        onError?.(error)
      }
    } finally {
      loading.value = false
      onFinally?.()
    }
}

fetchData 函数中,我们根据配置项的设置来发起数据请求,并根据返回结果更新相应的数据。同时,在请求过程中,我们可以调用成功、失败和结束时的回调函数,以便处理额外的逻辑。

完整的代码和 Demo 可以在我的 GitHub 仓库 ares-admin 中查看。

总结

通过 useTable 函数,我们可以轻松实现一些常见的业务功能,提高代码的可维护性和复用性,节省开发时间。需要注意的是,由于本文中 useTable 没有在项目中实践,可能有一些不完善的地方,仅供参考学习。

最后,欢迎大家在评论区讨论学习,分享自己的经验和更好的想法。