Vue3 + Element Plus 实现高复用表格组件

2天前

#vue

Vue3 + Element Plus 实现高复用表格组件:TableLayout & useTablePagination 全解

目录

  1. 组件概述
  2. 核心功能
  3. 组件 API
  4. useTablePagination 钩子
  5. 使用示例
  6. 最佳实践

引言

在企业级中后台系统中,列表表格是使用频率最高的组件之一。随着项目的增长,复制粘贴的表格逻辑会导致大量重复代码和维护成本。为了解决这一问题,我们封装了一个通用的 TableLayout 组件,并配合分页钩子 useTablePagination,统一管理分页、排序、查询等逻辑。

组件概述

TableLayout 是一个功能完整的表格布局组件,集成了查询区域、操作区域、表格展示和分页功能。该组件基于 Element Plus 的 el-table 组件进行封装,并结合 useTablePagination 钩子实现了数据加载和分页的统一管理。

特点

  • 响应式布局设计
  • 集成查询区域(可折叠)
  • 支持表格列显示控制
  • 内置分页功能
  • 支持表格排序
  • 自适应高度计算

核心功能

1. 布局结构

TableLayout
├── 查询区域 (可折叠)
├── 表格区域
│   ├── 操作工具栏
│   ├── 表格主体
│   └── 分页器
└── 右侧工具栏

2. 数据管理

  • 使用 useTablePagination 钩子统一管理表格数据
  • 支持数据格式化
  • 支持自定义查询参数
  • 内置加载状态管理

组件 API

Props

属性名类型默认值说明
fetchApiFunction() => 数据获取函数
paramsObject查询参数对象
formatDataFunctiondata => data数据格式化函数
isPaginationBooleantrue是否显示分页
defaultSortObjectnull默认排序配置
...attrs--可接受所有el-table的参数或者方法

Slots

插槽名说明
query查询区域内容
operation操作区域内容
table表格列定义

useTablePagination 钩子

功能说明

提供表格数据加载、分页管理的统一解决方案。

参数

typescript
function useTablePagination<T>(api: ApiParam<T>, options: TableOptions<T>): TablePaginationResult;

选项接口

typescript
interface 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. 查询参数管理

typescript
const queryParams = ref({ pageNum: 1, pageSize: 10, keyword: '', status: null });

2. API 封装

typescript
import { request } from '@/utils/request'; export function getList(params: QueryParams) { return request({ url: '/api/list', method: 'get', params }); }

3. 数据格式化

typescript
const 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>

注意事项

  1. 确保 fetchApi 返回的数据格式符合 PageApiResult 接口要求
  2. 使用 formatData 处理特殊的数据转换需求
  3. 合理使用 immediate 选项控制初始加载
  4. 注意表格高度自适应可能受父容器影响
  5. 排序功能需要后端支持,确保接口能正确处理排序参数
  6. 查询区域的折叠状态会被保持,可通过右侧工具栏控制

类型定义

PageApiResult 接口

typescript
interface PageApiResult<T> { rows: T[]; total: number; }

QueryParams 接口

typescript
interface QueryParams { pageNum: number; pageSize: number; orderByColumn?: string; isAsc?: string; [key: string]: any; }

Sort 接口

typescript
interface Sort { prop: string; order: 'ascending' | 'descending'; }

总结

通过 TableLayoutuseTablePagination 的组合,可以极大地提升列表页的开发效率与一致性。该方案适用于中后台系统的通用数据列表场景,推荐在团队项目中统一规范使用。

👉 项目源码地址 欢迎 Star 或提出建议。

如果你在实践中遇到问题,欢迎评论交流。

目录