Vue3 封装属于自己的 useTableData hook

624 阅读2分钟

在Vue.js 3中,"hook"(钩子)指的是一组特定的函数,用于在组件的生命周期中执行特定的操作。可以使用Composition API创建自定义钩子(Custom Hooks)。自定义钩子允许将可重用的逻辑封装在一个函数中,并在多个组件中共享。

要创建自定义钩子,请遵循以下步骤:

  1. 创建一个函数,命名为以 "use" 开头的名称,以表示它是一个钩子函数。例如,useCustomHook
  2. 在该函数内部定义您希望共享的逻辑,可以包括响应式数据、计算属性、方法等。
  3. 返回一个对象,其中包含需要在组件中使用的数据和方法。
  4. 在组件中使用自定义钩子函数。可以使用解构赋值或直接引用钩子函数返回的对象。

首先需要思考一个问题,这个 hook 接受什么参数,返回什么参数。现在没想好,不要紧,写着写着就知道了。

useTableData 中返回了 getTableData 函数。这个函数在成功之后,调用 setTableData 函数设置 table 的数据。

设置 tableData 中的参数有很多种情况,我们无法一一去控制,所以我们就需要把这部分的工作交给外界。

import { ref, reactive, nextTick } from 'vue'

function useTableData(tableParams) {

  const getTableData = async () => {
    const params = {
      ...tableParams
    }

    tableLoading.value = true
    await request(params)
      .then((res: any) => {
        setTableData(res, tableData)
      })
      .finally(() => {
        tableLoading.value = false
      })
  }

  return { getTableData }
}

export default useTableData

表格分页器是标配,当分页器的page 变化,size 变化的时候,去请求新的数据

import { ref, reactive, nextTick } from 'vue'

function useTableData() {
  const pagination = reactive({
    total: 0,
    page,
    pageSize,
    pageChange: async (page: number) => {
      await getTableData()
    },
    sizeChange(pageSize: number) {
      pagination.page = 1
      pagination.pageSize = pageSize
      getTableData()
    }
  })

  return { pagination, getTableData }
}

export default useTableData

最后加上一些细节的优化

  • 可以设置是否需要自动请求
  • 把tableLoading, tableData 这两个数据传递出去

这是最终的实现效果

import { ref, reactive, nextTick } from 'vue'

interface Params {
  getTableParams: Function
  setTableData: Function
  request: Function
  autoRequest?: boolean
  page?: number
  pageSize?: number
  pageName?: string
  pageSizeName?: string
}

function useTableData({
  getTableParams,
  setTableData,
  request,
  autoRequest = true,
  page = 1,
  pageSize = 10,
  pageName = 'page',
  pageSizeName = 'page_size'
}: Params) {
  const tableLoading = ref(false)
  const tableData = ref([] as any[])
  const tableParams = getTableParams()

  const pagination = reactive({
    total: 0,
    page,
    pageSize,
    pageChange: async (page: number) => {
      await getTableData()
    },
    sizeChange(pageSize: number) {
      pagination.page = 1
      pagination.pageSize = pageSize
      getTableData()
    }
  })

  const getTableData = async (page?: number, addParams?: any) => {
    const params = {
      ...tableParams,
      ...getTableParams(),
      ...addParams
    }

    pagination.page = page || pagination.page
    params[pageName] = pagination.page
    params[pageSizeName] = pagination.pageSize

    tableLoading.value = true
    await request(params)
      .then((res: any) => {
        setTableData(res, tableData)
      })
      .finally(() => {
        tableLoading.value = false
      })
  }

  // 是否自动请求
  if (autoRequest) {
    getTableData()
  }

  return { tableLoading, tableData, pagination, getTableData }
}

export default useTableData