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% 模块。


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

相关推荐
悟能不能悟43 分钟前
js闭包问题
开发语言·前端·javascript
秋秋_瑶瑶1 小时前
vue-amap组件呈现的效果图如何截图
前端·javascript·vue-amap
骥龙1 小时前
零信任架构:重塑现代企业安全基石
安全·架构
LFly_ice2 小时前
学习React-9-useSyncExternalStore
javascript·学习·react.js
gnip2 小时前
js上下文
前端·javascript
中草药z2 小时前
【Stream API】高效简化集合处理
java·前端·javascript·stream·parallelstream·并行流
不知名raver(学python版)3 小时前
npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR!
前端·npm·node.js
醉方休3 小时前
React中使用DDD(领域驱动设计)
前端·react.js·前端框架
excel3 小时前
📖 小说网站的预导航实战:link 预加载 + fetch + 前进后退全支持
前端