🪜 写在前面
前端系统中,表格(Table)是信息密度最高、交互复杂度最高的组件之一。 它常常包含以下复杂场景:
- 动态列配置、字段格式化、宽度控制
- 嵌套子表格、展开行、折叠树结构
- 表格内表单、权限控制、按钮操作栏
- 表格导出、多选、分页、远程过滤等
这篇文章,我们将架构一套「高度解耦 + 插槽灵活 + 列驱动配置 + 支持复杂交互」的通用表格系统组件,同时给出数据流、状态管理、UI 封装的完整路径。
📦 一、表格系统结构设计
bash
components/
├── DataTable.vue # 主组件(通用表格)
├── columns/ # 自定义列渲染
│ ├── DateColumn.vue
│ ├── StatusColumn.vue
│ ├── ActionColumn.vue
hooks/
├── useTable.ts # 表格数据逻辑封装
├── useColumns.ts # 列配置处理封装
utils/
├── format.ts # 单元格格式化方法
🧠 二、核心设计:列配置驱动渲染
列配置:
ts
const columns = [
{
title: '用户名',
key: 'username',
width: 120,
type: 'text',
},
{
title: '创建时间',
key: 'createdAt',
width: 180,
type: 'date',
format: 'YYYY-MM-DD HH:mm',
},
{
title: '状态',
key: 'status',
type: 'tag',
colorMap: {
active: 'green',
disabled: 'gray',
},
},
{
title: '操作',
key: 'actions',
type: 'actions',
buttons: [
{ label: '编辑', permission: 'user.edit', onClick: (row) => edit(row) },
{ label: '删除', permission: 'user.delete', confirm: true, onClick: deleteUser },
],
},
]
✅ 三、表格组件结构(DataTable.vue)
vue
<template>
<Table :columns="renderedColumns" :data="tableData" :loading="loading">
<template #[col.key]="{ row }" v-for="col in slotColumns">
<component
:is="getColumnRender(col)"
:row="row"
:column="col"
/>
</template>
</Table>
</template>
🎯 四、表格渲染类型支持(type 映射)
ts
function getColumnRender(col) {
return {
text: DefaultCell,
date: DateColumn,
tag: StatusColumn,
actions: ActionColumn,
}[col.type || 'text']
}
DefaultCell
:纯文本渲染DateColumn
:格式化时间StatusColumn
:颜色标识 + 状态文字ActionColumn
:支持按钮权限判断、确认弹窗
🔁 五、表格数据逻辑封装(useTable)
ts
export function useTable(fetchFn) {
const tableData = ref([])
const loading = ref(false)
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
async function load() {
loading.value = true
const res = await fetchFn({ page: pagination.page, size: pagination.pageSize })
tableData.value = res.list
pagination.total = res.total
loading.value = false
}
return {
tableData,
loading,
pagination,
reload: load,
}
}
页面中使用:
ts
const { tableData, loading, pagination, reload } = useTable(fetchUserList)
🧩 六、操作栏按钮组件(ActionColumn.vue)
vue
<template>
<div class="actions">
<pf-button
v-for="btn in buttons"
v-if="hasPermission(btn.permission)"
@click="handleClick(btn, row)"
:type="btn.type || 'default'"
>
{{ btn.label }}
</pf-button>
</div>
</template>
带确认:
ts
function handleClick(btn, row) {
if (btn.confirm) {
confirm(`确认执行 ${btn.label} 吗?`).then(() => btn.onClick(row))
} else {
btn.onClick(row)
}
}
📑 七、嵌套子表格 / 展开行实现
支持配置:
ts
{
type: 'expand',
renderExpand: (row) => h(UserDetail, { user: row }),
}
组件内处理:
vue
<template #expand="{ row }">
<component :is="columns.find(c => c.key === 'expand').renderExpand(row)" />
</template>
✅ 八、通用功能支持建议
功能 | 实现建议 |
---|---|
多选 | Table props: rowSelection , 返回选中项 |
分页 | pagination 统一封装,支持组件联动 |
过滤 | 支持列级 filter,可使用 el-table 或 naive-ui |
导出 | 将当前数据导出为 CSV/Excel(使用 SheetJS) |
拖拽列宽 | 使用 el-table 的 resizable 或自定义拖拽逻辑 |
💡 九、组件扩展点建议
扩展点 | 插槽/属性 |
---|---|
表头插槽 | #header |
空数据插槽 | #empty |
行样式控制 | row-class-name 函数 |
行点击事件 | @row-click |
列级 slot | #[column.key] 动态命名插槽 |
🧠 十、表格系统平台化建议
若做"可配置化运营表格系统",推荐将配置 JSON 化:
json
{
"columns": [
{ "label": "用户名", "key": "username", "type": "text" },
{ "label": "角色", "key": "role", "type": "tag", "colorMap": { "admin": "red" } },
{ "label": "操作", "type": "actions", "buttons": [ ... ] }
],
"api": "/api/user/list",
"pagination": true,
"export": true
}
动态加载表格配置 + 数据,实现一套平台表格系统。
🧠 总结一句话
表格系统就是"组件 + 配置 + 数据 + 权限 + 联动"的缩影,做好表格系统,你就能做前端的 70% 模块。
下一篇我们进入系统基础建设中「国际化支持」模块: 👉 《前端多语言国际化架构设计》