Table 组件设计文档
概述
Table 组件是本组件库中用于展示表格数据的核心组件。它延续了我们组件库一贯的设计理念,采用"关注点分离"和"逻辑抽象"的原则,通过 table.vue 和 tableColumn.vue等核心组件实现了一套完整且易用的表格解决方案。
Table 组件专注于处理表格数据的展示、交互和样式管理,为用户提供了一套强大、灵活的表格管理功能,支持基本表格、树形表格、行选择、行展开等多种功能,有效提升用户在处理结构化数据时的体验。
设计理念
分层架构
Table 组件严格按照三层架构设计:
- 结构层 table.vue, tableColumn.vue - 负责组件的 DOM 结构和基本布局
- 逻辑层 table.ts, tableComputed.ts - 处理复杂的响应式计算和交互逻辑
- 表现层 table.scss - 定义组件的视觉呈现和样式规则
逻辑抽象
Table 组件将复杂的逻辑抽象为核心函数:
- useTableComputed - 处理表格的核心逻辑
- flattenTreeData - 处理树形数据的扁平化
- toggleRowExpansion - 处理行展开/折叠逻辑
- toggleRowSelection - 处理行选择逻辑
这种设计使得组件本身只需要声明所需逻辑,而具体的计算由逻辑函数完成。
核心功能设计
Props 结构化设计
Table 组件的 props 设计简洁明了:
typescript
export const tableProps = {
/** 表格数据 */
data: {
type: Array as () => Record<string, unknown>[],
default: () => []
},
/** 列定义 */
columns: {
type: Array as () => TableColumnProps[],
default: () => []
},
/** 选中行 */
modelValue: {
type: [Array, String] as PropType<string[] | number[] | string>,
default: () => []
},
/** 表格宽度 */
width: {
type: String,
default: ''
},
/** 表格高度 */
height: {
type: String,
default: ''
},
/** 表头背景色 */
headerBackgroundColor: {
type: String,
default: ''
},
/** 表头文字颜色 */
headerTextColor: {
type: String,
default: ''
},
/** 斑马纹背景色 */
stripe: {
type: String,
default: ''
},
/** 边框颜色 */
borderColor: {
type: String,
default: ''
},
/** 表格体背景色 */
bodyBackgroundColor: {
type: String,
default: ''
},
/** 悬停背景色 */
hoverBackgroundColor: {
type: String,
default: ''
},
/** 表格体文字颜色 */
bodyTextColor: {
type: String,
default: ''
},
/** 行唯一标识 */
rowKey: {
type: String,
default: 'id'
},
/** 树形结构配置 */
treeProps: {
type: Object as () => {
children?: string;
hasChildren?: string;
},
default: () => ({
children: 'children',
hasChildren: 'hasChildren'
})
},
/** 树形缩进 */
indent: {
type: Number,
default: 16
},
/** 对齐方式 */
align: {
type: String as PropType<'left' | 'center' | 'right'>,
default: 'left'
},
/** 表头对齐方式 */
headerAlign: {
type: String as PropType<'left' | 'center' | 'right'>,
default: ''
},
/** 表体对齐方式 */
bodyAlign: {
type: String as PropType<'left' | 'center' | 'right'>,
default: ''
}
}参数说明:
- data:表格数据源。
- columns:列定义配置。
- modelValue:用于双向绑定选中的行。
- stripe:设置斑马纹背景色。
- treeProps:配置树形表格的子节点字段。
- indent:设置树形表格的缩进量。
列定义设计
TableColumn 组件的 props 设计:
typescript
export const tableColumnProps = {
/** 列属性 */
prop: {
type: String,
required: true
},
/** 列标题 */
label: {
type: String,
default: undefined
},
/** 列宽度 */
width: {
type: String,
default: ''
},
/** 固定列 */
fixed: {
type: String as PropType<'left' | 'right'>,
default: undefined
},
/** 是否可排序 */
sortable: {
type: Boolean,
default: false
},
/** 对齐方式 */
align: {
type: String as PropType<'left' | 'right' | 'center'>,
default: ''
},
/** 表头对齐方式 */
headerAlign: {
type: String as PropType<'left' | 'right' | 'center'>,
default: ''
},
/** 表体对齐方式 */
bodyAlign: {
type: String as PropType<'left' | 'right' | 'center'>,
default: ''
},
/** 列类型 */
type: {
type: String,
default: ''
}
}列类型支持:
- 普通数据列:通过 prop 和 label定义
- 选择列:通过
type="selection"定义 - 树形列:通过 prop 和树形数据结构定义
样式系统设计
CSS 变量控制
Table 组件通过 CSS 变量实现样式控制:
--table-border-color- 表格边框颜色--hover-bg-color- 行悬停背景色
布局系统
Table 组件支持灵活的布局控制:
- 表格布局 - 使用
table-layout: auto实现自适应 - 列宽控制 - 通过 width 属性控制列宽
- 对齐方式 - 支持全局和列级别的对齐配置
- 树形结构 - 通过缩进实现层次关系展示
状态样式
Table 组件根据不同状态提供相应的样式:
- 默认状态 - 标准表格样式
- 悬停状态 - 行悬停时的背景色变化
- 斑马纹状态 - 交替行背景色
- 展开状态 - 树形表格展开/折叠状态
- 选中状态 - 行选中状态
组件结构设计
整体结构
Table 组件的整体结构如下:
html
<div class="my-table" :style="{ '--table-border-color': props.borderColor, ...tableStyle }">
<table>
<thead :style="headerStyle">
<tr>
<th v-for="column in columnsWithWidth" :key="column.prop" :style="getColumnStyle(column, 'header')">
<!-- 列头内容 -->
</th>
</tr>
</thead>
<tbody :style="bodyStyle">
<tr v-for="(item, index) in flatTableData" :key="getRowKey(item.row)"
:style="index % 2 === 1 ? { backgroundColor: props.stripe } : {}">
<td v-for="column in columnsWithWidth" :key="column.prop" :style="getColumnStyle(column, 'body')">
<!-- 单元格内容 -->
</td>
</tr>
</tbody>
</table>
<div class="pagination-container">
<slot name="pagination"></slot>
</div>
</div>组件层次
Table 组件包含多个主要部分:
- 容器 -
.my-table- 包裹整个表格组件 - 表头 -
thead- 表格头部区域 - 表体 -
tbody- 表格主体区域 - 行 -
tr- 单个表格行 - 单元格 -
td- 单个单元格 - 分页容器 -
.pagination-container- 放置分页组件
TableColumn 组件作为声明性组件:
html
<MYTableColumn prop="name" label="姓名" width="150px" />交互设计
树形数据处理
Table 组件通过 flattenTreeData 处理树形数据:
typescript
const flattenTreeData = (
data: RowRecord[],
level = 0,
parent: RowRecord | null = null
): Array<{ row: RowRecord; level: number; parent: RowRecord | null; isLeaf: boolean }> => {
const result: Array<{ row: RowRecord; level: number; parent: RowRecord | null; isLeaf: boolean }> = [];
data.forEach((item) => {
const children = getChildren(item);
const isLeaf = children.length === 0;
result.push({
row: item,
level,
parent,
isLeaf,
});
if (!isLeaf && isRowExpanded(item)) {
result.push(...flattenTreeData(children, level + 1, item));
}
});
return result;
};行展开/折叠
Table 组件通过 toggleRowExpansion 实现行展开/折叠:
typescript
const toggleRowExpansion = (row: RowRecord, expanded?: boolean) => {
const key = getRowKey(row);
const index = expandedRowKeys.value.indexOf(key);
const isExpanded = index !== -1;
if (expanded === undefined) expanded = !isExpanded;
if (expanded && !isExpanded) {
expandedRowKeys.value.push(key);
} else if (!expanded && isExpanded) {
expandedRowKeys.value.splice(index, 1);
}
};行选择功能
Table 组件通过 toggleRowSelection 实现行选择:
typescript
const toggleRowSelection = (row: RowRecord) => {
const key = getRowKey(row);
const index = selectedRows.value.findIndex((s) => getRowKey(s as RowRecord) === key);
if (index > -1) {
selectedRows.value.splice(index, 1);
} else {
selectedRows.value.push(row);
}
emitUpdate();
};事件系统:
- update:modelValue:当选中行变化时触发
- selection-change:当选中行变化时触发
扩展性设计
Table 组件具备良好的扩展性:
- 列定义:通过 columns 属性和 tableColumn 组件灵活定义列
- 插槽支持:通过插槽机制自定义单元格内容vue
<MYTable :data="data" :columns="columns"> <template #name="{ row }"> <span style="color: red">{{ row.name }}</span> </template> </MYTable> - 样式定制:通过多种颜色属性自定义表格样式
- 树形结构:通过 treeProps 和 indent 支持树形表格
- 分页集成:通过
pagination插槽集成分页组件
样式细节
Table 组件在样式处理上有以下特点:
- 响应式设计:支持灵活的布局适配
- 一致性:与组件库其他组件保持样式一致性
- 无障碍设计:确保键盘导航和屏幕阅读器友好
- 状态反馈:提供清晰的视觉反馈(如悬停状态、选中状态)
- 动画效果:展开/折叠有平滑的过渡效果
性能优化
通过以下方式优化性能:
- 使用计算属性缓存表格数据处理结果
- 将复杂逻辑移至独立的函数中
- 避免不必要的重新渲染
- 使用 Vue 3 Composition API 提高运行效率
- 按需渲染树形表格的子节点
- 使用 CSS 变量动态调整样式
设计价值
Table 组件延续了我们组件库的设计哲学:
- 关注点分离:结构、样式、逻辑完全解耦
- 高度复用:通过函数抽象通用逻辑
- 易于维护:清晰的代码结构和命名规范
- 可扩展性强:支持丰富的定制选项
- 一致性:与 DataGrid、ListView 等其他组件保持一致的设计语言