Skip to content

useTable 表格数据管理钩子函数文档

一、功能概述

useTable 是基于 Vue 3 的响应式表格数据管理钩子,用于统一处理表格数据的加载、分页、搜索和格式化。它封装了常见的表格操作逻辑,支持与后端接口集成,适用于中后台管理系统的表格场景。

二、核心特性

  1. 响应式状态管理

    • 包含加载状态 loading、表格数据 data、分页信息 pagination 等响应式数据
    • 状态变化时自动触发视图更新
  2. 灵活的分页支持

    • 可通过 hasPagination 开关控制是否启用分页
    • 支持自定义分页初始值(通过 pagination 函数传入)
  3. 多功能数据处理

    • 自动合并查询参数与分页参数
    • 支持数据格式化(formatter 函数)
    • 提供搜索(onSearch)、刷新(onRefresh)等常用操作
  4. 可配置化接口

    • 支持动态传入 API 接口、查询参数、初始化加载等配置

三、接口定义

1. 分页参数接口(Pagination

typescript
interface Pagination {
  pageNo: number; // 当前页码(从 1 开始)
  pageSize: number; // 每页条数
  total: number; // 总数据量
}

2. 表格状态接口(TableState

typescript
interface TableState {
  pagination: Pagination; // 分页状态
  loading: boolean; // 加载状态
  data: any[]; // 表格数据
}

3. 钩子函数参数(UseTableProps

参数名类型必填默认值说明
api(params: any) => Promise<any>-数据请求接口(需返回 Promise)
query() => any{}查询参数生成函数(返回对象,可异步)
formatter(data: any[]) => any[]-数据格式化函数(用于处理接口返回的原始数据)
hasPaginationbooleantrue是否启用分页
initbooleantrue是否在初始化时自动加载数据
pagination() => Pagination() => ({ pageNo: 1, pageSize: 10, total: 1 })分页初始值生成函数

四、返回值说明

名称类型说明
paginationRef<Pagination>分页状态响应式对象
loadingRef<boolean>加载状态响应式变量
dataRef<any[]>表格数据响应式数组
onSearch() => Promise<void>搜索函数(重置页码为 1 并重新加载数据)
onRefresh() => Promise<void>刷新函数(保留当前页码并重新加载数据)
loadData() => Promise<void>数据加载函数(可手动调用)
hasPaginationboolean是否启用分页的标识值

五、使用示例

场景 1:基础表格(带分页)

vue
<template>
  <div>
    <el-table :data="data" v-loading="loading">
      <el-table-column prop="name" label="姓名" />
      <el-table-column prop="age" label="年龄" />
    </el-table>
    
    <el-pagination
      v-if="hasPagination"
      :total="pagination.total"
      :current-page="pagination.pageNo"
      :page-size="pagination.pageSize"
      @current-change="(pageNo) => { pagination.pageNo = pageNo; loadData(); }"
      @size-change="(pageSize) => { pagination.pageSize = pageSize; loadData(); }"
    />
  </div>
</template>

<script setup>
import { useTable } from '@eco-library/hooks';
import { getUsers } from '@/api/user'; // 假设存在该接口

const { data, loading, pagination, loadData } = useTable({
  api: getUsers, // 接口函数(需返回 { data: { list, total } } 格式)
  query: () => ({ status: 'active' }), // 固定查询参数
  formatter: (list) => list.map(item => ({ ...item, age: item.age + 1 })), // 数据格式化
});

// 手动触发搜索
const handleSearch = () => {
  onSearch();
};
</script>

场景 2:无分页表格(字典数据)

vue
<template>
  <el-table :data="data" v-loading="loading" />
</template>

<script setup>
import { useTable } from '@eco-library/hooks';
import { getDictData } from '@/api/dict'; // 返回平铺数组

const { data, loading } = useTable({
  api: getDictData,
  hasPagination: false, // 关闭分页
  formatter: (data) => data.map(item => ({ label: item.name, value: item.id })),
});
</script>

场景 3:动态查询参数(带搜索框)

vue
<template>
  <el-input v-model="searchKey" placeholder="搜索姓名" @change="handleSearch" />
  <TableComponent />
</template>

<script setup>
import { ref } from 'vue';
import { useTable } from '@eco-library/hooks';
import { searchUsers } from '@/api/user'; // 支持 keyword 参数

const searchKey = ref('');

const { onSearch } = useTable({
  api: searchUsers,
  query: async () => ({ keyword: searchKey.value }), // 动态查询参数(支持异步)
});

const handleSearch = () => {
  onSearch(); // 触发搜索并重置页码
};
</script>

六、注意事项

  1. 接口返回格式要求

    • 启用分页时,接口需返回 { data: { list: any[], total: number } } 格式
    • 关闭分页时,接口需返回 { data: any[] } 或直接返回数组
  2. 性能优化

    • 大数据量场景建议开启虚拟滚动(如使用 vue-virtual-scroller
    • 可通过 nextTick 确保 DOM 更新后再执行数据加载(如动态获取查询参数)
  3. 类型安全
    建议为 api 接口和 formatter 函数添加类型声明,避免运行时错误:

    typescript
    interface User { name: string; age: number; }
    const formatter: (data: User[]) => User[] = (list) => list;

七、扩展建议

1. 支持动态列配置

typescript
// 扩展钩子,添加列配置管理
export function useTableWithColumns<T>(props: UseTableProps<T>) {
  const { data, ...rest } = useTable(props);
  const columns = ref<TableColumn<T>[]>([
    { prop: 'name', label: '姓名' },
    { prop: 'age', label: '年龄' }
  ]);
  return { ...rest, columns };
}

2. 添加加载更多功能

typescript
// 扩展钩子,支持滚动加载更多
export function useTableInfiniteScroll(props: UseTableProps) {
  const { loadData, pagination, hasPagination } = useTable(props);
  
  const loadMore = async () => {
    if (!hasPagination || pagination.value.pageNo * pagination.value.pageSize >= pagination.value.total) return;
    pagination.value.pageNo++;
    await loadData();
  };

  return { ...rest, loadMore };
}

八、依赖说明

  • 核心依赖:Vue 3.x(reactivetoRefsnextTick
  • 工具函数xCloneDeep(深度克隆工具,需确保其兼容性)
  • UI 组件:示例中使用 Element Plus,实际使用时需替换为项目组件库

仅供内部学习使用