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


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

相关推荐
学Java的bb4 小时前
JavaWeb-后端Web实战(IOC + DI)
前端
pe7er5 小时前
React Native 多环境配置全攻略:环境变量、iOS Scheme 和 Android Build Variant
前端·react native·react.js
柯北(jvxiao)5 小时前
Vue vs React 多维度剖析: 哪一个更适合大型项目?
前端·vue·react
JefferyXZF5 小时前
Next.js 中间件:掌握请求拦截与处理的核心机制(六)
前端·全栈·next.js
知识分享小能手5 小时前
Vue3 学习教程,从入门到精通,Vue 3 + Tailwind CSS 全面知识点与案例详解(31)
前端·javascript·css·vue.js·学习·typescript·vue3
石小石Orz5 小时前
React生态蓝图梳理:前端、全栈与跨平台全景指南
前端
袁煦丞6 小时前
8.12实验室 指尖魔法变出艺术感 Excalidraw:cpolar内网穿透实验室第495个成功挑战
前端·程序员·远程工作
烛阴6 小时前
Dot
前端·webgl
Gene_20226 小时前
使用行为树控制机器人(三) ——通用端口
前端·机器人
excel7 小时前
JavaScript 中的二进制数据:ArrayBuffer 与 SharedArrayBuffer 全面解析
前端