13、表格系统架构:列配置、嵌套数据、复杂交互

🪜 写在前面

前端系统中,表格(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-tableresizable 或自定义拖拽逻辑

💡 九、组件扩展点建议

扩展点 插槽/属性
表头插槽 #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% 模块。


下一篇我们进入系统基础建设中「国际化支持」模块: 👉 《前端多语言国际化架构设计》

相关推荐
Real_man5 分钟前
新物种与新法则:AI重塑开发与产品未来
前端·后端·面试
小彭努力中5 分钟前
147.在 Vue3 中使用 OpenLayers 地图上 ECharts 模拟飞机循环飞行
前端·javascript·vue.js·ecmascript·echarts
老马聊技术7 分钟前
日历插件-FullCalendar的详细使用
前端·javascript
zhu_zhu_xia9 分钟前
cesium添加原生MVT矢量瓦片方案
javascript·arcgis·webgl·cesium
咔咔一顿操作10 分钟前
Cesium实战:交互式多边形绘制与编辑功能完全指南(最终修复版)
前端·javascript·3d·vue
coding随想1 小时前
JavaScript中的系统对话框:alert、confirm、prompt
开发语言·javascript·prompt
LuckyLay1 小时前
使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
前端·docker·rust
pobu1682 小时前
aksk前端签名实现
java·前端·javascript
森焱森2 小时前
单片机中 main() 函数无 while 循环的后果及应对策略
c语言·单片机·算法·架构·无人机