Vue3自定义useTable

背景

在后台管理系统中充斥着大量的搜索+表格的页面,需要重复定义 loading,page,tableData getData()等变量或方法,急需封装一个hook减少重复工作,useTable是最好的选择.

hook封装

hook接收请求地址,请求参数等参数,实现请求数据功能,并返回分页,数据类别,加载状态

formatParams:请求参数params解构后将不能动态获取form的变化,所有定义了formatParams方法用于修改入参

formatResult:处理请求返回的列表,并将格式化后的结果保存到tableData中,当然也你可以在onSuccess的回调中处理

onSuccess:请求成功的回调

pagination: 用于分页,分页改变后将自动重新请求

useList.js 完整代码

js 复制代码
import { onMounted, ref, watch } from 'vue'
import { post } from '@/utils/request'
import { message } from 'ant-design-vue'
/**
 * @name: useTable
 * @description: 获取列表数据
 */
export default function ({ url, params, formatParams, formatResult, onSuccess, immediate }) {
  const loading = ref(false)
  const pagination = ref({ total: 0, current: 1, pageSize: 10 })
  const tableData = ref([])
  //请求部分需结合具体项目修改
  const getData = async () => {
    loading.value = true
    const { code, data, msg, total } = await post(url, {
      ...(formatParams ? formatParams(params) : params),
      pageNum: pagination.value.current,
      pageSize: pagination.value.pageSize
    })
    loading.value = false
    if (code !== 0) return message.error(msg || '请求失败')
    tableData.value = formatResult ? formatResult(data) : data
    pagination.value.total = total
    onSuccess && onSuccess(data)
  }
  //分页改变
  watch(pagination, () => getData())
  //初始化请求
  onMounted(() => immediate && getData())

  return { loading, tableData, pagination, getData }
}

使用示例

UI框架使用Ant Design Vue,示例省略部分代码

html 复制代码
<template>
  <a-form :model="formState">
    <a-form-item name="key" label="名称">
      <a-input v-model:value="formState.name" placeholder="请输入" />
    </a-form-item>
    <a-form-item name="stdate" label="日期范围">
      <a-range-picker v-model:value="formState['range-picker']" />
    </a-form-item>
  </a-form>
  <a-table :loading="loading" :columns="columns" :data-source="tableData" :pagination="pagination" @change="(page) => (pagination = page)" />
</template>
<script setup>
import { ref } from 'vue'
import columns from './columns'
import useTable from './useTable'
const formState = ref({})
const { loading, tableData, pagination, getData } = useTable({
  url: '/api/xxxxx', //请求路径
  immediate: true, //立即请求
  params: formState.value, //请求入参 此处必须为ref对象,且不能解构
  formatParams: (params) => { //格式化入参
    return {
      ...params,
      startDate: params['range-picker'][0],
      endDate: params['range-picker'][1]
    }
  },
  formatResult: (res) => {  //格式化结果
    //...
  },
  onSuccess: (res) => {     //成功回调
    //...
  }
})
</script>

对比

在不使用useTable的情况下,代码如下,可以看出封装useTable大大减少重复工作,不用在每个表格下定义分页和loading,而且代码更简洁易懂。

html 复制代码
<template>
<a-form :model="formState">
...
</a-form>
<a-table
    :loading="loading"
    :columns="columns"
    :data-source="tableData"
    :pagination="page"
    @change="onPageChange"
  />
</template>  
<script setup>
import { ref, getData } from 'vue'
import useTable from './useTable'
import columns from './columns'
import { post } from '@/utils/request'
const loading = ref(false)
const tableData = ref([])
const formState = ref({})
const page = ref({ total: 0, current: 1, pageSize: 10 })
//请求数据
const getData = async () => {
  loading.value = true
  const { code, data, total } = await post('/api/xxxx', {
    ...formState.value,
    startDate: formState.value['range-picker'][0],
    endDate: formState.value['range-picker'][1],
    pageNum: page.value.current,
    pageSize: page.value.pageSize
  })
  loading.value = false
  if (code !== 0) return
  tableData.value = data
  page.value.total = total
}
//分页改变
const onPageChange = ({ current, pageSize }) => {
  page.value.current = current
  page.value.pageSize = pageSize
  getData()
}
//初始化请求
onMounted(() => getData())
</script>

结尾

如有更好的意见或建议,欢迎留言探讨

相关推荐
lovingsoft5 分钟前
Chrome Lighthouse 详解
前端·chrome
Qlly15 分钟前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝19 分钟前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦20 分钟前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡40 分钟前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI1 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战
汉堡大王95271 小时前
单次输出拉到100万Token:拆完 Gemini 4 Argon 的续写协议,才看懂谷歌这7个月在憋什么
前端·人工智能·后端
看浪的路人1 小时前
第9讲:大模型应用监控与可观测性——OpenTelemetry + Prometheus + Grafana 全链路追踪
java·前端·spring
内存过载1 小时前
用表格模拟甘特图:项目排期的土办法
前端·低代码
葡萄城技术团队1 小时前
用 SpreadJS 数据验证实现省市区三级联动
前端