🪜 写在前面
前端系统中,表格(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% 模块。
下一篇我们进入系统基础建设中「国际化支持」模块: 👉 《前端多语言国际化架构设计》