表格
概述
用于展示行列数据的数据表格组件。STable 将 Aria 层 TableCompact 聚合组件(TableRoot 一族的 9 个基础原语,零样式)与 tableVariants 样式配方(29 个槽位,7 种尺寸 × 2 种视觉变体)组合。支持配置式 columns(分组表头、index/selection/expand 类型列)、排序、筛选、多选/单选、展开行与树形行、固定列/表头、列宽拖拽调整与键盘调整、虚拟滚动与空状态展示;default/simple 两种变体配合 bordered/rounded/striped 开关。所有交互文案与 aria-label(排序、筛选、选择、展开、列宽调整)均经 useLocaleMessages 本地化。
用法
特性
- 📋 配置式列模型 — TanStack 优先的
columns: TableColumn<T>[](accessorKey/header/size/minSize+ VeanUI 扩展align/type/fixed/hidden),分组表头(columns)、index/selection/expand类型列;rowKey保证行身份稳定 - 🔀 排序 — 列上
enableSorting: true(或sortFn自定义比较);受控sorting/v-model:sorting(TanStackSortingState);aria-sort+ 排序按钮aria-label本地化 - 🔍 筛选 — 列上
enableColumnFilter: true(+filterPlaceholder/filterOptions);{ keyword, values }复合筛选值,弹层内关键字搜索、选项多选、汇总计数与清除操作全部本地化;状态为 TanStackColumnFiltersState(v-model:columnFilters) - ✅ 选择 — 默认多选(
multiple默认true,复选框 + 表头全选),multiple={false}切换为单选(行内 radio);受控selected/v-model:selected - 🧩 展开与树形 —
expand类型列或expanded-row插槽渲染展开行;children/getChildren驱动树形行(引擎getSubRows);expanded遵循 TanStackExpandedState - 📐 固定与调整 —
fixed: 'start' | 'end'播种 TanStack 列固定(pinning)+ 阴影渐变指示;resizable列支持指针拖拽与方向键键盘调整,写入 TanStackcolumnSizing(aria-label本地化) - ⚡ 性能 —
virtual+height启用虚拟滚动(自定义estimateSize/virtualizerOptions),仅渲染可视行 - 🎛️ 引擎逃生舱 — 插槽 props 携带
table/engineColumn引擎实例;useTableEngine()在表格子树任意位置注入引擎;模板 ref 暴露table;tableOptionsprop 透传原始 TanStack 选项(分页、行选择、manual 服务端模式、meta、initialState…) - 🌐 默认本地化 — 空状态、排序/筛选/选择/展开/列宽调整的
aria-label与筛选弹层文案全部经useLocaleMessages(21 条table.*消息,14 语言包)
组件家族
STable(styled)— 入口包装;tableVariants配方(29 槽位 = 16 个 Aria 槽 + 11 个筛选/选择扩展槽 + 2 个内部 radio 槽);useOmitProps转发 +useForwardListeners事件合并 + 全插槽透传;注入默认header-selection/selection/header-sort/header-filter/header-resize/tree-toggle/expand/empty插槽内容TableCompact(Aria)— 聚合状态所有者,构建在@tanstack/vue-table引擎之上:useTableCompactState(sorting/columnFilters/expanded/columnPinning/columnSizing经useControllableState,selected/multiple经useSelection)、useTableCompactTable(引擎实例接线)、useTableCompactData(表头分组/叶子列/行模型)、useTableCompactResize(指针 + 键盘列宽)、useTableCompactVirtual;provideTableCompactContext桥接 9 个原语TableRoot(Aria)— 根元素,dir方向,渲染data-vean-table-root与表语义容器TableScroll/TableContent/TableHeader/TableBody/TableFooter/TableRow/TableHead/TableCell(Aria)— 9 个基础原语,全部零样式,渲染data-vean-table-*数据属性TableCompactHead/TableCompactRow/TableCompactCell/TableCompactExpandedRow/TableVirtualSpacerRow(Aria 内部)— Compact 聚合内部的组合与渲染组件(不对外导出)STableFilterPopover(styled 内部)— 筛选弹层(SPopover + SInput + SCheckbox + SButton),本地化搜索/选项/汇总/清除STableRadio(styled 内部)— 单选模式的行内 radio 按钮(aria-pressed语义),直接消费tableVariants的radioRoot/radioIndicator槽useTable/usePaginatedTable(UI hooks)— 客户端排序/筛选/分页组合钩子
演示
基础
| # | Name | Age | Header Address | Details |
|---|---|---|---|---|
| 1 | John Doe | 30 | 123 Main St | |
| 2 | Jane Smith | 25 | 456 Elm St | |
| 3 | Bob Johnson | 40 | 789 Oak St | |
| 4 | Alice Brown | 35 | 321 Pine St | |
| 5 | Charlie Davis | 28 | 654 Maple | Detail for Charlie Davis |
| 6 | Eve White | 32 | 987 Cedar St | |
| 7 | Frank Green | 45 | 246 Birch St | |
| 8 | Grace Lee | 27 | 135 Spruce St | |
| 9 | Hank Miller | 38 | 864 Willow St | |
| 10 | Ivy Wilson | 29 | 753 Aspen St |
空状态
| # | Name | Age | Address |
|---|---|---|---|
暂无数据当前没有可显示的数据。 | |||
| # | Name | Age | Address |
|---|---|---|---|
No matching recordsTry adjusting filters or create the first record from here. | |||
分组
| Profile | Metrics | ||
|---|---|---|---|
| Name | City | Age | Score |
| Ada Lovelace | London | 36 | 96 |
| Linus Torvalds | Helsinki | 28 | 88 |
| Grace Hopper | New York | 41 | 92 |
排序
| Name | Age | Score |
|---|---|---|
| Ada Lovelace | 36 | 96 |
| Linus Torvalds | 28 | 88 |
| Grace Hopper | 41 | 92 |
过滤
| Name | City | Score |
|---|---|---|
| Ada Lovelace | London | 96 |
| Linus Torvalds | Helsinki | 88 |
| Grace Hopper | New York | 92 |
固定
Two columns stay pinned on the left and the score stays pinned on the right while the table scrolls horizontally.
| Employee ID | Name | Role | Team | Status | Location | Timezone | Phone | Projects | Utilization | Last Updated | Score | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ENG-001 | Ada Lovelace | Architect | Core Platform | Active | London | UTC+0 | [email protected] | +44 20 7946 001 | 4 | 91% | 2026-04-10 | 96 |
| ENG-014 | Linus Torvalds | Maintainer | Kernel Systems | Reviewing | Helsinki | UTC+2 | [email protected] | +358 9 1234 014 | 6 | 84% | 2026-04-12 | 88 |
| ENG-021 | Grace Hopper | Scientist | Developer Experience | Active | New York | UTC-4 | [email protected] | +1 212 555 0021 | 5 | 89% | 2026-04-14 | 92 |
| ENG-037 | Margaret Hamilton | Tech Lead | Design Systems | Planning | Boston | UTC-4 | [email protected] | +1 617 555 0037 | 3 | 76% | 2026-04-09 | 94 |
| ENG-052 | Katherine Johnson | Analyst | Data Intelligence | Active | Hampton | UTC-4 | [email protected] | +1 757 555 0052 | 7 | 93% | 2026-04-13 | 98 |
可调整列宽
Drag any header handle to adjust the column width.
| Employee ID | Name | Role | Team | Status | Location | Timezone | Phone | Projects | Utilization | Last Updated | Score | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ENG-001 | Ada Lovelace | Architect | Core Platform | Active | London | UTC+0 | [email protected] | +44 20 7946 001 | 4 | 91% | 2026-04-10 | 96 |
| ENG-014 | Linus Torvalds | Maintainer | Kernel Systems | Reviewing | Helsinki | UTC+2 | [email protected] | +358 9 1234 014 | 6 | 84% | 2026-04-12 | 88 |
| ENG-021 | Grace Hopper | Scientist | Developer Experience | Active | New York | UTC-4 | [email protected] | +1 212 555 0021 | 5 | 89% | 2026-04-14 | 92 |
| ENG-037 | Margaret Hamilton | Tech Lead | Design Systems | Planning | Boston | UTC-4 | [email protected] | +1 617 555 0037 | 3 | 76% | 2026-04-09 | 94 |
| ENG-052 | Katherine Johnson | Analyst | Data Intelligence | Active | Hampton | UTC-4 | [email protected] | +1 757 555 0052 | 7 | 93% | 2026-04-13 | 98 |
树形
| Name | Age | Role |
|---|---|---|
Engineering | 12 | Department |
Platform Team | 6 | Team |
Design Team | 4 | Team |
Operations | 8 | Department |
虚拟滚动
| # | Name | Age | Address |
|---|---|---|---|
| 1 | User 1 | 20 | Block 1, Soybean Street |
| 2 | User 2 | 21 | Block 2, Soybean Street |
| 3 | User 3 | 22 | Block 3, Soybean Street |
| 4 | User 4 | 23 | Block 4, Soybean Street |
| 5 | User 5 | 24 | Block 5, Soybean Street |
| 6 | User 6 | 25 | Block 6, Soybean Street |
| 7 | User 7 | 26 | Block 7, Soybean Street |
| 8 | User 8 | 27 | Block 8, Soybean Street |
| 9 | User 9 | 28 | Block 9, Soybean Street |
| 10 | User 10 | 29 | Block 10, Soybean Street |
| 11 | User 11 | 30 | Block 11, Soybean Street |
| 12 | User 12 | 31 | Block 12, Soybean Street |
| 13 | User 13 | 32 | Block 13, Soybean Street |
| 14 | User 14 | 33 | Block 14, Soybean Street |
| 15 | User 15 | 34 | Block 15, Soybean Street |
| 16 | User 16 | 35 | Block 16, Soybean Street |
可展开
| Name | Age | Address | |
|---|---|---|---|
| John Doe | 30 | 123 Main St | |
| Jane Smith | 25 | 456 Elm St | |
| Bob Johnson | 40 | 789 Oak St |
底部
| # | Name | Age | Address |
|---|---|---|---|
| 1 | John Doe | 30 | 123 Main St |
| 2 | Jane Smith | 25 | 456 Elm St |
| 3 | Bob Johnson | 40 | 789 Oak St |
Total: 3 items | |||
底部
| # | Name | Age | Address |
|---|---|---|---|
| 1 | John Doe | 30 | 123 Main St |
| 2 | Jane Smith | 25 | 456 Elm St |
| 3 | Bob Johnson | 40 | 789 Oak St |
多选
| Name | Age | Address | |
|---|---|---|---|
| John Doe | 30 | 123 Main St | |
| Jane Smith | 25 | 456 Elm St | |
| Bob Johnson | 40 | 789 Oak St |
单选
| Name | Age | Address | |
|---|---|---|---|
| John Doe | 30 | 123 Main St | |
| Jane Smith | 25 | 456 Elm St | |
| Bob Johnson | 40 | 789 Oak St |
行事件
| Name | Role | Region |
|---|---|---|
| Ada Lovelace | Architect | London |
| Linus Torvalds | Maintainer | Helsinki |
| Grace Hopper | Compiler Lead | New York |
Latest row event
Click, double click, or right click a row to inspect the emitted payload.
- rowKey
- -
- index
- -
- level
- -
rowData
{
"rowData": null
}rowMouseenter and rowMouseleave use the same payload shape when you need hover-driven behavior.
- 01 Basic — 基础
columns+data渲染 - 02 Variant —
default/simple视觉变体 - 03 Bordered —
bordered边框开关 - 04 Rounded —
rounded圆角开关 - 05 Striped —
striped斑马纹 - 06 Empty — 空状态(默认 SEmpty 与自定义
empty插槽) - 07 Grouped — 分组表头(
columns) - 08 Sorting —
enableSorting+sortFn+ 受控/非受控排序 - 09 Filtering —
enableColumnFilter选项与关键字筛选弹层 - 10 Fixed —
fixed: 'start' | 'end'固定列 - 11 Resizable —
resizable列宽拖拽/键盘调整 - 12 Tree — 树形行(数据
children+tree-toggle) - 13 Virtualized —
virtual+height虚拟滚动 - 14 Expandable —
expand列与expanded-row插槽 - 15 Footer —
footer汇总插槽 - 16 Bottom —
bottom底部插槽 - 17 Multiple Selection — 多选(复选框 + 全选)
- 18 Single Selection —
multiple={false}单选(radio) - 19 Row Events —
rowClick/rowDblclick/rowContextmenu等行事件 - 20 Sizes — 7 种尺寸(xs–2xl)
API
Aria 层
29Table<T, R, M>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 需应用于表格的其他类名。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | Partial<TableExtendedUi> | — | 该组件的按槽类重写。 |
variant | TableVariant | — | 该组件的视觉变体。 |
bordered | boolean | — | 是否带边框。 |
rounded | boolean | — | 是否四舍五入。 |
striped | boolean | — | 是否采用条纹样式。 |
columns | TableColumn<T>[] | — | 列定义。TanStack 的列定义具有最高优先级。 |
data | T[] | — | 数据。 |
rowKey | (row: T) => R | — | 行键。 |
getChildren | ((row: T) => T[]) | — | 嵌套子节点解析器用作引擎的 `getSubRows`。 |
sorting | SortingState | — | 排序状态(TanStack `SortingState`)。 |
defaultSorting | SortingState | — | 默认排序状态。 |
tableOptions | TableEngineOptions | — | 通过 TanStack `useTable` 调用传递的引擎选项。该
组件拥有的键(data、columns、state wiring、owned change handlers)将
被该组件覆盖;其余所有选项将解锁引擎的
全部功能(分页、行选择、手动模式、meta、initialState...)。 |
columnFilters | ColumnFiltersState | — | 列过滤器状态(TanStack `ColumnFiltersState`)。过滤器值接受
由内置过滤器处理的复合格式 `{ 关键字, 值 }`。 |
defaultColumnFilters | ColumnFiltersState | — | 默认列过滤器状态。 |
expanded | ExpandedState | — | 展开状态(TanStack `ExpandedState`)。 |
defaultExpanded | ExpandedState | — | 默认展开状态。 |
defaultExpandAll | boolean | — | 是否默认展开所有行。 |
columnPinning | ColumnPinningState | — | 列固定状态(TanStack `ColumnPinningState`)。当此属性缺失时,列的 `fixed`
字段将作为默认状态的初始值。 |
defaultColumnPinning | ColumnPinningState | — | 默认列固定状态。 |
columnSizing | ColumnSizingState | — | 列尺寸状态(TanStack `ColumnSizingState`,以列 ID 为键的 px 值)。 |
defaultColumnSizing | ColumnSizingState | — | 默认列宽设置状态。 |
indent | number | — | 对嵌套项应用缩进宽度。 |
virtual | boolean | — | 是否为虚拟。 |
height | string | number | — | 高度。 |
estimateSize | number | ((index: number, row: T) => number) | — | 估算文档篇幅。 |
virtualizerOptions | VirtualizerOptions | — | Virtualizer 选项。 |
contentProps | TableContentProps | — | 转发给内容元素的属性。 |
headerProps | TableHeaderProps | — | 转发至 header 元素的属性。 |
bodyProps | TableBodyProps | — | 转发至 body 元素的属性。 |
footerProps | TableFooterProps | — | 转发至页脚元素的属性。 |
headProps | TableHeadProps | — | 转发至 head 元素的属性。 |
rowProps | TableRowProps | — | 转发给 row 元素的属性。 |
cellProps | TableCellProps | — | 转发给 cell 元素的属性。 |
dir | Direction | — | 组件的阅读方向。 |
defaultSelected | (M extends true ? R[] : R) | — | 默认选中。 |
selected | (M extends true ? R[] : R) | — | 该项是否已被选中。 |
multiple | M | — | 是否支持多个值。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:sorting | SortingState | 在排序状态值发生变化时触发。 |
update:columnFilters | ColumnFiltersState | 当列过滤器状态值发生变化时触发。 |
update:expanded | ExpandedState | 当展开后的状态值发生变化时触发。 |
update:columnPinning | ColumnPinningState | 当列固定状态值发生变化时触发。 |
update:columnSizing | ColumnSizingState | 当列宽调整状态值发生变化时触发。 |
update:selected | M extends true ? R[] : R | undefined | 在选定状态发生变化时触发。 |
rowClick | MouseEvent, payload: TableRowEventPayload<T, R> | 在点击行时触发。 |
rowDblclick | MouseEvent, payload: TableRowEventPayload<T, R> | 当双击某行时触发。 |
rowContextmenu | MouseEvent, payload: TableRowEventPayload<T, R> | 在触发行上下文菜单时触发。 |
rowMouseenter | MouseEvent, payload: TableRowEventPayload<T, R> | 当指针进入一行时触发。 |
rowMouseleave | MouseEvent, payload: TableRowEventPayload<T, R> | 当指针离开一行时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
bottom | — | 底部区域的自定义内容。 |
header | TableHeaderSlotProps<T> | 用于页眉插槽的自定义内容。 |
header-index | { column: TableColumn<T>; } | 用于页眉索引位置的自定义内容。 |
header-selection | TableHeaderSelectionSlotProps<T> | 用于页眉选择槽位的自定义内容。 |
header-expand | { column: TableColumn<T>; } | 用于页眉展开区域的自定义内容。 |
header-filter | TableHeaderFilterSlotProps<T> | 用于标题过滤器插槽的自定义内容。 |
header-sort | TableHeaderSortSlotProps<T> | 用于页眉排序槽位的自定义内容。 |
header-resize | TableHeaderResizeSlotProps<T> | 用于页眉调整大小插槽的自定义内容。 |
index | TableIndexSlotProps<T> | 索引槽位的自定义内容。 |
selection | TableSelectionSlotProps<T> | 用于选择槽位的自定义内容。 |
expand | TableExpandSlotProps<T> | “展开”区域的自定义内容。 |
expanded-row | TableExpandedRowSlotProps<T> | 用于展开行插槽的自定义内容。 |
tree-toggle | TableTreeToggleSlotProps<T> | 树状结构切换按钮的自定义内容。 |
empty | TableEmptySlotProps | 为空槽位添加自定义内容。 |
footer | { columnSize: number; } | 页脚位置的自定义内容。 |
TableBody
TableCell
TableCompact<T, R, M>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
columns | TableColumn<T>[] | — | 列定义。TanStack 的列定义具有最高优先级。 |
data | T[] | — | 数据。 |
rowKey | (row: T) => R | — | 行键。 |
getChildren | ((row: T) => T[]) | — | 嵌套子节点解析器用作引擎的 `getSubRows`。 |
sorting | SortingState | — | 排序状态(TanStack `SortingState`)。 |
defaultSorting | SortingState | — | 默认排序状态。 |
tableOptions | TableEngineOptions | — | 通过 TanStack `useTable` 调用传递的引擎选项。该
组件拥有的键(data、columns、state wiring、owned change handlers)将
被该组件覆盖;其余所有选项将解锁引擎的
全部功能(分页、行选择、手动模式、meta、initialState...)。 |
columnFilters | ColumnFiltersState | — | 列过滤器状态(TanStack `ColumnFiltersState`)。过滤器值接受
由内置过滤器处理的复合格式 `{ 关键字, 值 }`。 |
defaultColumnFilters | ColumnFiltersState | — | 默认列过滤器状态。 |
expanded | ExpandedState | — | 展开状态(TanStack `ExpandedState`)。 |
defaultExpanded | ExpandedState | — | 默认展开状态。 |
defaultExpandAll | boolean | — | 是否默认展开所有行。 |
columnPinning | ColumnPinningState | — | 列固定状态(TanStack `ColumnPinningState`)。当此属性缺失时,列的 `fixed`
字段将作为默认状态的初始值。 |
defaultColumnPinning | ColumnPinningState | — | 默认列固定状态。 |
columnSizing | ColumnSizingState | — | 列尺寸状态(TanStack `ColumnSizingState`,以列 ID 为键的 px 值)。 |
defaultColumnSizing | ColumnSizingState | — | 默认列宽设置状态。 |
indent | number | — | 对嵌套项应用缩进宽度。 |
virtual | boolean | — | 是否为虚拟。 |
height | string | number | — | 高度。 |
estimateSize | number | ((index: number, row: T) => number) | — | 估算文档篇幅。 |
virtualizerOptions | VirtualizerOptions | — | Virtualizer 选项。 |
contentProps | TableContentProps | — | 转发给内容元素的属性。 |
headerProps | TableHeaderProps | — | 转发至 header 元素的属性。 |
bodyProps | TableBodyProps | — | 转发至 body 元素的属性。 |
footerProps | TableFooterProps | — | 转发至页脚元素的属性。 |
headProps | TableHeadProps | — | 转发至 head 元素的属性。 |
rowProps | TableRowProps | — | 转发给 row 元素的属性。 |
cellProps | TableCellProps | — | 转发给 cell 元素的属性。 |
dir | Direction | — | 组件的阅读方向。 |
defaultSelected | (M extends true ? R[] : R) | — | 默认选中。 |
selected | (M extends true ? R[] : R) | — | 该项是否已被选中。 |
multiple | M | — | 是否支持多个值。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
update:sorting | SortingState | 在排序状态值发生变化时触发。 |
update:columnFilters | ColumnFiltersState | 当列过滤器状态值发生变化时触发。 |
update:expanded | ExpandedState | 当展开后的状态值发生变化时触发。 |
update:columnPinning | ColumnPinningState | 当列固定状态值发生变化时触发。 |
update:columnSizing | ColumnSizingState | 当列宽调整状态值发生变化时触发。 |
update:selected | M extends true ? R[] : R | undefined | 在选定状态发生变化时触发。 |
rowClick | MouseEvent, payload: TableRowEventPayload<T, R> | 在点击行时触发。 |
rowDblclick | MouseEvent, payload: TableRowEventPayload<T, R> | 当双击某行时触发。 |
rowContextmenu | MouseEvent, payload: TableRowEventPayload<T, R> | 在触发行上下文菜单时触发。 |
rowMouseenter | MouseEvent, payload: TableRowEventPayload<T, R> | 当指针进入一行时触发。 |
rowMouseleave | MouseEvent, payload: TableRowEventPayload<T, R> | 当指针离开一行时触发。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
bottom | — | 底部区域的自定义内容。 |
header | TableHeaderSlotProps<T> | 用于页眉插槽的自定义内容。 |
header-index | { column: TableColumn<T>; } | 用于页眉索引位置的自定义内容。 |
header-selection | TableHeaderSelectionSlotProps<T> | 用于页眉选择槽位的自定义内容。 |
header-expand | { column: TableColumn<T>; } | 用于页眉展开区域的自定义内容。 |
header-filter | TableHeaderFilterSlotProps<T> | 用于标题过滤器插槽的自定义内容。 |
header-sort | TableHeaderSortSlotProps<T> | 用于页眉排序槽位的自定义内容。 |
header-resize | TableHeaderResizeSlotProps<T> | 用于页眉调整大小插槽的自定义内容。 |
index | TableIndexSlotProps<T> | 索引槽位的自定义内容。 |
selection | TableSelectionSlotProps<T> | 用于选择槽位的自定义内容。 |
expand | TableExpandSlotProps<T> | “展开”区域的自定义内容。 |
expanded-row | TableExpandedRowSlotProps<T> | 用于展开行插槽的自定义内容。 |
tree-toggle | TableTreeToggleSlotProps<T> | 树状结构切换按钮的自定义内容。 |
empty | TableEmptySlotProps | 为空槽位添加自定义内容。 |
footer | { columnSize: number; } | 页脚位置的自定义内容。 |
TableCompactCell
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
column | TableColumn<T extends TableBaseData = TableBaseData> | — | 列定义。 |
row | TableTreeRow<T extends TableBaseData = TableBaseData, R extends TableUnifiedKey = TableUnifiedKey> | — | 行。 |
index | number | — | 当前条目的索引。 |
插槽
| 插槽名 | 参数 | 描述 |
|---|---|---|
index | TableIndexSlotProps<T> | 索引槽位的自定义内容。 |
selection | TableSelectionSlotProps<T> | 用于选择槽位的自定义内容。 |
expand | TableExpandSlotProps<T> | “展开”区域的自定义内容。 |
tree-toggle | TableTreeToggleSlotProps<T> | 树状结构切换按钮的自定义内容。 |
TableCompactExpandedRow
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
row | TableTreeRow<T extends TableBaseData = TableBaseData, R extends TableUnifiedKey = TableUnifiedKey> | — | 行。 |
index | number | — | 当前条目的索引。 |
colspan | number | — | Colspan。 |
TableCompactHead
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
header | TableEngineHeader<T extends TableBaseData = TableBaseData> | — | 引擎头文件实例。 |
TableCompactRow
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
row | TableTreeRow<T extends TableBaseData = TableBaseData, R extends TableUnifiedKey = TableUnifiedKey> | — | 行。 |
index | number | — | 当前条目的索引。 |
leafColumns | TableColumn<TableBaseData>[] | — | 叶子列。 |
TableContent
TableDataCell
TableEmpty
TableExpand
TableExpandedRow
TableFilterPopover<T>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
size | ThemeSize | — | 组件的视觉尺寸。 |
ui | TableExtendedUi | — | 该组件的按槽类重写。 |
column | TableColumn<T extends TableBaseData = TableBaseData> | — | 在插槽作用域中暴露的列定义。 |
filterValue | string | — | 过滤在插槽作用域中暴露的值。 |
filterValues | string[] | — | 过滤在插槽作用域中暴露的值。 |
filterState | TableFilterValue | — | 过滤在插槽作用域中暴露的状态。 |
filtered | boolean | — | 是否经过过滤。 |
filterOptions | TableColumnFilterOption[] | — | 过滤在插槽作用域中暴露的选项。 |
setFilterValue | (value: string) => void | — | 设置在插槽作用域中暴露的过滤器值。 |
setFilterValues | (values: string[]) => void | — | 设置在插槽作用域中暴露的过滤器值。 |
setFilterState | (value: TableFilterValue | undefined) => void | — | 在插槽作用域中设置暴露的过滤器状态。 |
toggleFilterOption | (value: string) => void | — | 在插槽作用域中显示过滤器选项。 |
isFilterOptionSelected | (value: string) => boolean | — | 是否选中了过滤选项。 |
clearFilter | () => void | — | 清除在插槽作用域中暴露的过滤器。 |
TableFooter
TableHead
TableHeader
TableHeaderFilter
TableHeaderResize
TableHeaderSelection
TableHeaderSort
TableIndex
TableRadio
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
size | ThemeSize | — | 组件的视觉尺寸。 |
checked | boolean | — | 该项是否已勾选。 |
TableRoot
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
dir | Direction | — | 组件的阅读方向。 |
TableRow
TableScroll
TableSelection<R, M>
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
defaultSelected | (M extends true ? R[] : R) | — | 默认选中。 |
selected | (M extends true ? R[] : R) | — | 该项是否已被选中。 |
multiple | M | — | 是否支持多个值。 |
TableTreeToggle
TableVirtualSpacerRow
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
isVirtual | boolean | — | 是否启用了虚拟滚动。 |
colspan | number | — | 分隔符所占的列数。 |
paddingStart | number | — | 在行首添加了填充。 |
paddingEnd | number | — | 在行尾添加填充。 |
说明
架构与对标差异
表格引擎为 @tanstack/vue-table(v9):列定义、排序、筛选、展开、固定、列宽均遵循 TanStack 状态契约(SortingState、ColumnFiltersState、ExpandedState、ColumnPinningState、ColumnSizingState),且全部经 useControllableState + useSelection 提供受控/非受控双通道;所有基础原语保持零样式,仅 UI 包装注入 tableVariants 类名。筛选弹层与单选 radio 作为 UI 内部组件被默认插槽消费,但消费者可用同名插槽(header-filter/selection 等)整体替换。排序按钮与筛选触发器为绝对定位图标按钮,配合本地化 aria-label 保持可访问;列宽调整同时支持指针(PointerEvent)与键盘(方向键)两种通道。虚拟滚动基于 @vean/aria 内置 virtualizer,仅渲染可视行并同步测量列宽。而 Ant Design / Element Plus 的表格为声明式组件实例(el-table-column),固定列依赖配置类名;VeanUI 的受控状态与 aria-sort 语义、以及全链路本地化(含筛选弹层)超出多数主流库。
| 能力 | VeanUI | Ant Design | Element Plus | Naive UI | Mantine Table |
|---|---|---|---|---|---|
| Aria/样式分离 | ✅ | — | — | — | — |
| 配置式 columns + 分组表头 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 排序(aria-sort + 受控/非受控) | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 筛选(关键字 + 选项多选) | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 选择(多选/单选 + 全选) | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 展开行 + 树形行 | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 固定列 / 固定表头 | ✅ | ✅ | ✅ | ✅ | ⚠️ |
| 列宽拖拽 + 键盘调整 | ✅ | ✅ | ⚠️ | ✅ | — |
| 虚拟滚动 | ✅ | ✅ | ⚠️ | ✅ | ⚠️ |
⚠️ = 部分支持(Mantine Table 的排序/筛选/选择为手动实现;Element Plus 虚拟滚动仅存在于独立的 el-table-v2;Element Plus 列宽拖拽仅限 border 模式)。
注意事项
- 列定义为 TanStack
ColumnDef优先:数据列用accessorKey(或accessorFn),header为标题,size/minSize为像素列宽。旧dataIndex/title字段已移除,需重命名为accessorKey/header。 - 排序、筛选、调整列宽均为列级 opt-in:
enableSorting、enableColumnFilter、resizable(默认全为false)。 - 分组列经
columns嵌套(TanStack 形状);树形行经行数据children字段或getChildren嵌套——二者是不同概念、不同字段。 multiple默认true(多选);设置为false后行内渲染 radio,此时selected为单值(R | undefined),表头全选复选框不渲染。- 排序/筛选/展开/固定/列宽均为受控/非受控双通道:传入
sorting等值时必须同时监听对应的update:sorting(或使用v-model:sorting)完成回写,否则状态不会更新。 expanded受控状态为 TanStackExpandedState,以String(rowKey(row))为键({ '1': true },或true表示全部);defaultExpandAll仅在非受控展开(无expanded)时生效。- 列筛选生效期间树形行强制展开,保证被筛中的祖先行可见。
- 虚拟滚动需要设置
height;未设置高度时virtual不生效(回退为普通渲染)。 - 固定列在
data-fixed单元格上注入背景色,fixed列阴影通过data-fixed-last-start/data-fixed-first-end数据属性绘制渐变;自定义cell/row插槽时请保留这些数据属性以维持视觉一致性。 - 筛选弹层文案(汇总、关键字、选项、清除)与空状态跟随 ConfigProvider 语言环境;列名取自
header→id/accessorKey回退链。
常见问题
如何实现行选择并获取选中行数据?
使用 multiple(默认多选)配合 v-model:selected 与 rowKey:
<STable :columns="columns" :data="data" :row-key="row => row.id" v-model:selected="selected" />selected 为选中行的 rowKey 数组;需要完整行数据时用 rowKey 反查 data。
如何做单选表格?
设置 multiple={false}——行内渲染 radio 按钮,selected 变为单值:
<STable :columns="columns" :data="data" :row-key="row => row.id" :multiple="false" v-model:selected="selected" />如何自定义筛选弹层?
使用 header-filter 插槽整体替换默认的 STableFilterPopover,或在列上配置 enableColumnFilter(filterOptions/filterPlaceholder):
<STable :columns="columns" :data="data" :row-key="row => row.id">
<template #header-filter="{ column, filtered, filterValues, setFilterValues, clearFilter }">
<!-- 自定义筛选控件 -->
</template>
</STable>如何控制排序/筛选的初始值?
用非受控 defaultSorting/defaultColumnFilters 初始化,之后由组件内部维护;需要外部同步时改用受控通道并监听 update:sorting/update:columnFilters:
<STable :columns="columns" :data="data" :row-key="row => row.id" :default-sorting="[{ id: 'age', desc: false }]" />大数据量如何优化?
启用虚拟滚动(virtual + height)并按需自定义 estimateSize;引擎行模型自带 memoization,1000 行规模下无需额外处理。
如何实现表格汇总行?
使用 footer 插槽——它接收 columnSize,配合 columns 逐列渲染汇总单元格:
<STable :columns="columns" :data="data" :row-key="row => row.id">
<template #footer="{ columnSize }">
<STableRow>
<STableCell>合计</STableCell>
<!-- 按需渲染汇总值 -->
</STableRow>
</template>
</STable>如何本地化表格文案?
空状态与所有交互 aria-label(排序/筛选/选择/展开/列宽)跟随 ConfigProvider 的 locale(table.* 消息,14 语言包);需要按实例覆盖时通过 ConfigProvider 的 messages 覆盖对应键,或使用同名插槽自定义内容。
引擎逃生舱
STable 是组件驱动的封装,但 TanStack 引擎从不锁死——提供四级逃生舱:
- 插槽 props — 每个表头/数据单元格插槽都接收
table(引擎表实例)与engineColumn(引擎列实例),连同column/row/value:
<STable :columns="columns" :data="data" :row-key="row => row.id">
<template #age="{ value, table }">
{{ value }}(共 {{ table.getPreFilteredRowModel().flatRows.length }} 行)
</template>
</STable>useTableEngine()— 在表格子树内渲染的任意组件中注入引擎(深层自定义单元格、工具栏组件):
import { useTableEngine } from '@vean/aria/table';
const table = useTableEngine();
table.value.setGrouping([{ id: 'city' }]);- 模板 ref — 引擎实例即暴露根对象,从组件外部直接控制:
const tableRef = useTemplateRef<TableEngineTable>('tableRef');
tableRef.value.previousPage();tableOptionsprop — 透传原始 TanStack 表选项,解锁组件未显式接线的能力(分页、行选择模型、manual 服务端模式、meta、initialState、faceted 值…)。组件自有的键(状态接线、变更处理器)优先:
<STable
:columns="columns"
:data="data"
:row-key="row => row.id"
:table-options="{
enableRowSelection: true,
getFilteredSelectedRowModel: createFilteredSelectedRowModel()
}"
/>单元格定制优先级:具名插槽 > columnDef.cell 渲染函数(TanStack 原生方式,经 FlexRender 渲染)> 纯文本值。表头遵循同样的链(columnDef.header)。
从 v0.4x 迁移
v0.50.0 将自研列模型更换为 @tanstack/vue-table。TanStack 命名为第一公民,旧字段不保留别名(dataIndex / sortState 等需按下表手动重命名),最高频的旧字段映射如下:
| v0.4x(旧) | v0.50.0(TanStack 优先) |
|---|---|
{ title, dataIndex } | { header, accessorKey }(dataIndex 别名已移除) |
sorter: true / sorter(a, b) | enableSorting: true / sortFn: (rowA, rowB) => number |
filter: true / filter: { ... } | enableColumnFilter: true / filterPlaceholder / filterOptions |
width: '140px' / minWidth | size: 140 / minSize(px 数值) |
分组列 { key, children } | { id, columns }(TanStack 分组形状) |
sortState / defaultSortState | sorting / defaultSorting(SortingState)—— 别名已移除 |
filterState / defaultFilterState | columnFilters / defaultColumnFilters(ColumnFiltersState) |
columnWidths / defaultColumnWidths | columnSizing / defaultColumnSizing(Record<string, number>) |
expanded: R[] | expanded: ExpandedState({ '1': true } 或 true) |
update:sortState / update:filterState | update:sorting / update:columnFilters |
迁移前后对照
<!-- v0.4x -->
<script setup>
const columns = [
{ title: 'Name', dataIndex: 'name', sorter: true, width: '180px' },
{ title: 'Age', dataIndex: 'age', align: 'center', filter: true }
];
const expanded = ref([1]);
</script>
<!-- v0.50.0 -->
<script setup>
const columns = [
{ header: 'Name', accessorKey: 'name', enableSorting: true, size: 180 },
{ header: 'Age', accessorKey: 'age', align: 'center', enableColumnFilter: true }
];
const expanded = ref({ 1: true });
</script>