Vue3 + Element Plus 实现高复用表格组件
2天前
Vue3 + Element Plus 实现高复用表格组件:TableLayout & useTablePagination 全解
目录
引言
在企业级中后台系统中,列表表格是使用频率最高的组件之一。随着项目的增长,复制粘贴的表格逻辑会导致大量重复代码和维护成本。为了解决这一问题,我们封装了一个通用的 TableLayout
组件,并配合分页钩子 useTablePagination
,统一管理分页、排序、查询等逻辑。
组件概述
TableLayout
是一个功能完整的表格布局组件,集成了查询区域、操作区域、表格展示和分页功能。该组件基于 Element Plus 的 el-table
组件进行封装,并结合 useTablePagination
钩子实现了数据加载和分页的统一管理。
特点
- 响应式布局设计
- 集成查询区域(可折叠)
- 支持表格列显示控制
- 内置分页功能
- 支持表格排序
- 自适应高度计算
核心功能
1. 布局结构
TableLayout
├── 查询区域 (可折叠)
├── 表格区域
│ ├── 操作工具栏
│ ├── 表格主体
│ └── 分页器
└── 右侧工具栏
2. 数据管理
- 使用
useTablePagination
钩子统一管理表格数据 - 支持数据格式化
- 支持自定义查询参数
- 内置加载状态管理
组件 API
Props
属性名 | 类型 | 默认值 | 说明 |
---|---|---|---|
fetchApi | Function | () => | 数据获取函数 |
params | Object | 查询参数对象 | |
formatData | Function | data => data | 数据格式化函数 |
isPagination | Boolean | true | 是否显示分页 |
defaultSort | Object | null | 默认排序配置 |
...attrs | - | - | 可接受所有el-table 的参数或者方法 |
Slots
插槽名 | 说明 |
---|---|
query | 查询区域内容 |
operation | 操作区域内容 |
table | 表格列定义 |
useTablePagination 钩子
功能说明
提供表格数据加载、分页管理的统一解决方案。
参数
typescriptfunction useTablePagination<T>(api: ApiParam<T>, options: TableOptions<T>): TablePaginationResult;
选项接口
typescriptinterface TableOptions<T> { formatData?: (data: T[]) => any; immediate?: boolean; queryParams: ComputedRef<QueryParams> | QueryParams; }
返回值
typescript{ getTableData: () => Promise<void>; // 获取表格数据 pageRef: Ref<number>; // 当前页码 pageSizeRef: Ref<number>; // 每页条数 tableData: Ref<T[]>; // 表格数据 totalRef: Ref<number>; // 总条数 loadingRef: Ref<boolean>; // 加载状态 }
使用示例
基础用法
vue<template> <TableLayout :fetch-api="fetchList" :params="queryParams" :format-data="formatTableData"> <!-- 查询区域 --> <template #query> <el-form :model="queryParams"> <!-- 查询表单内容 --> </el-form> </template> <!-- 操作区域 --> <template #operation> <el-button type="primary">新增</el-button> </template> <!-- 表格内容 --> <template #table> <el-table-column prop="name" label="名称" /> <el-table-column prop="status" label="状态" /> </template> </TableLayout> </template> <script setup lang="ts"> import { ref } from 'vue'; const queryParams = ref({ pageNum: 1, pageSize: 10 // 其他查询参数 }); const fetchList = async (params) => { // 实现数据获取逻辑 return { rows: [], total: 0 }; }; const formatTableData = (data) => { // 数据格式化逻辑 return data; }; </script>
最佳实践
1. 查询参数管理
typescriptconst queryParams = ref({ pageNum: 1, pageSize: 10, keyword: '', status: null });
2. API 封装
typescriptimport { request } from '@/utils/request'; export function getList(params: QueryParams) { return request({ url: '/api/list', method: 'get', params }); }
3. 数据格式化
typescriptconst formatTableData = (data: any[]) => { return data.map((item) => ({ ...item, statusText: item.status === 1 ? '启用' : '禁用' })); };
4. 表格排序
vue<TableLayout :default-sort="{ prop: 'date', order: 'descending' }"> <template #table> <el-table-column prop="date" label="日期" sortable /> </template> </TableLayout>
注意事项
- 确保
fetchApi
返回的数据格式符合PageApiResult
接口要求 - 使用
formatData
处理特殊的数据转换需求 - 合理使用
immediate
选项控制初始加载 - 注意表格高度自适应可能受父容器影响
- 排序功能需要后端支持,确保接口能正确处理排序参数
- 查询区域的折叠状态会被保持,可通过右侧工具栏控制
类型定义
PageApiResult 接口
typescriptinterface PageApiResult<T> { rows: T[]; total: number; }
QueryParams 接口
typescriptinterface QueryParams { pageNum: number; pageSize: number; orderByColumn?: string; isAsc?: string; [key: string]: any; }
Sort 接口
typescriptinterface Sort { prop: string; order: 'ascending' | 'descending'; }
总结
通过 TableLayout
和 useTablePagination
的组合,可以极大地提升列表页的开发效率与一致性。该方案适用于中后台系统的通用数据列表场景,推荐在团队项目中统一规范使用。
👉 项目源码地址 欢迎 Star 或提出建议。
如果你在实践中遇到问题,欢迎评论交流。