# vtable-guild — full documentation > 面向 ant-design-vue 和 element-plus 用户的高性能 Vue 表格组件。以下为全部文档页的 markdown 原文。 --- ## 先动手,再读文档 ```vue // @/demos/home/overview.vue ``` 想看更大的场景,去 [10 万行虚拟滚动](/guide/virtualization);想改代码即时看效果,去 [Playground](/play/)。 ## 适合谁 vtable-guild 面向已经在项目中使用 ant-design-vue 或 element-plus 的团队。 如果你希望保留熟悉的表格使用方式,但又需要更稳定的虚拟滚动、列宽控制、主题扩展和更可维护的样式覆盖模型,这个库比继续在原表格外堆补丁更合适。 ## 你会先看哪条路线 - 想尽快接入: 看 [快速开始](/guide/getting-started) - 想先判断值不值得替换: 看 [功能对比总览](/comparison/) 和 [为什么选择 vtable-guild](/guide/why) - 想统一视觉体系: 看 [三层主题覆盖](/guide/theme-overrides) 和 [Table CSS 变量参考](/guide/theme-tokens) - 想直接查 API: 看 [API Reference](/guide/api-reference) 和 [类型参考](/guide/type-reference) --- # API Reference 这一页是组件行为参考:查 props、events、slots、默认值和受控规则。 如果你要查 `TableColumnsType`、`Breakpoint`、`RowSelection` 等 TypeScript 类型的完整关系,请看 [类型参考](/guide/type-reference)。这一页只引用类型名,不重复展开类型定义。 ## 导入入口 推荐从 `@vtable-guild/vtable-guild` 统一导入组件、常量和类型。 ```ts import { VTable, VTableSummary, EXPAND_COLUMN, SELECTION_COLUMN, type TableColumnsType, type RowSelection, type Expandable, } from '@vtable-guild/vtable-guild' ``` ## VTable Props ### 数据与结构 | Prop | 类型 | 默认值 | 说明 | | -------------------- | ---------------------------------------------------------------- | ------------ | -------------------------------------------------------------------------- | | `dataSource` | `TRecord[]` | `[]` | 表格数据源。 | | `columns` | [`TableColumnsType`](/guide/type-reference#columnstype) | `[]` | 列配置,支持叶子列、列组和列占位常量。 | | `columnOrder` | [`Key[]`](/guide/type-reference#key) | - | 列显示顺序,见[列显示与列顺序](/guide/column-display#列顺序-columnorder)。 | | `rowKey` | `string \| (record) => Key` | - | 行唯一标识,建议显式传入。 | | `childrenColumnName` | `string` | `'children'` | 树形数据的子节点字段名。 | | `indentSize` | `number` | `15` | 树形数据缩进宽度,单位 px。 | ### 视觉与布局 | Prop | 类型 | 默认值 | 说明 | | ---------------- | -------------------------------- | --------- | ----------------------------------------------------- | | `size` | `'small' \| 'middle' \| 'large'` | `'large'` | 表格尺寸,与 ant-design-vue 命名对齐。 | | `loading` | `boolean \| object` | `false` | 加载态;对象形式支持 `spinning`、`indicator`、`tip`。 | | `bordered` | `boolean` | `false` | 显示边框。 | | `striped` | `boolean` | `false` | 开启斑马纹。 | | `hoverable` | `boolean` | `true` | 开启行 hover 高亮。 | | `tableLayout` | `'auto' \| 'fixed'` | - | 表格布局模式。 | | `showHeader` | `boolean` | `true` | 是否显示表头。 | | `headerEllipsis` | `boolean` | `false` | 让开启了 `column.ellipsis` 的列表头也单行省略。 | | `class` | `string` | - | 根节点额外 class。 | ### 滚动与定位 | Prop | 类型 | 默认值 | 说明 | | ------------------- | ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scroll` | `{ x?: number \| string; y?: number \| string }` | - | 横向和纵向滚动配置;提供 `y` 时形成固定表头滚动区。`y: 'auto'` 表示自动适应内容区(组件内部扣减表头/固定 summary 高度,需父容器有确定高度,见[虚拟滚动](/guide/virtualization#自动高度-scrolly-auto))。 | | `sticky` | `boolean \| TableSticky` | `false` | 粘性表头、摘要行或横向滚动条配置。 | | `virtual` | `boolean` | `false` | 启用虚拟滚动;需要同时设置 `scroll.y`。 | | `virtualColumn` | `boolean` | `false` | 横向虚拟化,只渲染视口内的列;需要同时开启 `virtual`。列数很多时才有收益,见[虚拟滚动](/guide/virtualization#横向虚拟化-virtualcolumn)。 | | `rowHeight` | `number` | - | 固定行高(px),仅在 `virtual` 下生效。声明后跳过全部行高测量,可视区计算恒为 O(1)。仅当每行实际高度确实等于该值时才可传,见[虚拟滚动](/guide/virtualization#定高快路径-rowheight)。 | | `getPopupContainer` | `(triggerNode) => HTMLElement` | - | 筛选和选择菜单的挂载容器。 | ### 主题与语言 | Prop | 类型 | 默认值 | 说明 | | ----------------- | -------------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------- | | `ui` | `SlotProps` | - | 当前表实例的 theme slot class 覆盖。完整 slot 见 [ui Slot 参考](/guide/ui-slots-reference)。 | | `locale` | [`LocaleName`](/guide/type-reference#localename) | 全局配置或 `'zh-CN'` | 当前表实例使用的语言标识。 | | `locales` | [`LocaleRegistry`](/guide/type-reference#localeregistry) | `{}` | 当前实例额外注册的语言包。 | | `localeOverrides` | `DeepPartial` | `{}` | 当前实例的 locale 局部覆写。 | ### 交互能力 | Prop | 类型 | 默认值 | 说明 | | ------------------------ | ------------------------------------------------------------- | ------- | ---------------------------------------------------------------------- | | `rowSelection` | [`RowSelection`](/guide/type-reference#rowselection) | - | 开启行选择列。 | | `expandable` | [`Expandable`](/guide/type-reference#expandable) | - | 开启展开行能力。 | | `rowDraggable` | `boolean` | `false` | 开启行拖拽排序,见[行拖拽排序](/guide/row-drag-sort)。 | | `expandedRowKeys` | `Key[]` | - | 树形数据的受控展开 key 列表。 | | `defaultExpandedRowKeys` | `Key[]` | - | 树形数据的默认展开 key 列表。 | | `defaultExpandAllRows` | `boolean` | `false` | 树形数据默认展开所有节点。 | | `onExpand` | `(expanded, record) => void` | - | 树形数据展开/折叠回调。 | | `onExpandedRowsChange` | `(expandedKeys) => void` | - | 树形数据展开 key 变化回调。 | | `transformCellText` | `(opt) => unknown` | - | 统一转换单元格文本;`opt` 包含 `text`、`column`、`record` 和 `index`。 | | `showSorterTooltip` | `boolean` | `true` | 表级控制是否显示排序 tooltip,可被列级 `showSorterTooltip` 覆盖。 | | `sortDirections` | [`SortOrder[]`](/guide/type-reference#sortorder) | - | 表级排序方向列表,作为列级 `sortDirections` 的默认值。 | ### 自定义结构 | Prop | 类型 | 默认值 | 说明 | | ----------------- | ------------------------------------------ | ------ | ------------------------------------ | | `rowClassName` | `string \| RowClassName` | - | 为 body row 添加 class。 | | `customRow` | `GetComponentProps` | - | 为 body row 注入属性、事件和样式。 | | `customHeaderRow` | `(columns, index?) => CellAdditionalProps` | - | 为 header row 注入属性、事件和样式。 | | `title` | `(data) => VNodeChild` | - | 表格标题区域渲染函数。 | | `footer` | `(data) => VNodeChild` | - | 表格页脚区域渲染函数。 | ## Column 行为 ### 基础字段 | 字段 | 类型 | 默认值 | 说明 | | ------------ | -------------------------------------------------- | ------- | -------------------------------------------------------------------------- | | `key` | [`Key`](/guide/type-reference#key) | - | 列唯一标识,建议显式传入。 | | `title` | `VNodeChild \| function` | - | 列标题,可以是文本、VNode 或渲染函数。 | | `dataIndex` | [`DataIndex`](/guide/type-reference#dataindex) | - | 数据字段路径,如 `'name'` 或 `['address', 'city']`。 | | `width` | `number \| string` | - | 列宽,数字按 px 处理。 | | `align` | [`AlignType`](/guide/type-reference#aligntype) | - | 列内容对齐方式。 | | `ellipsis` | `boolean \| { showTitle?: boolean }` | `false` | 单元格内容超出时省略;`showTitle: false` 时不显示 hover tooltip。 | | `className` | `string` | - | 列单元格额外 class。 | | `colSpan` | `number` | - | 表头单元格跨列数。 | | `visible` | `boolean` | `true` | 控制列是否显示,见[列显示与列顺序](/guide/column-display#列显示-visible)。 | | `responsive` | [`Breakpoint[]`](/guide/type-reference#breakpoint) | - | 当前屏幕命中任一断点时显示该列。 | ### 自定义渲染 | 字段 | 类型 | 默认值 | 说明 | | ------------------ | ------------------------------------------------- | ------ | ------------------------------------------------------------------------- | | `customRender` | `(ctx) => VNodeChild \| RenderedCell` | - | 自定义 body cell 内容。返回 `RenderedCell` 时可同时设置内容和单元格属性。 | | `customCell` | `(record, index, column?) => CellAdditionalProps` | - | 为 body cell 注入属性、事件和样式。 | | `customHeaderCell` | `(column, index) => CellAdditionalProps` | - | 为 header cell 注入属性、事件和样式。 | ```ts customRender: ({ text, index }) => index === 0 ? { children: String(text), props: { colSpan: 2, style: { fontWeight: 'bold' } } } : String(text) ``` ### 固定列与列宽拖拽 | 字段 | 类型 | 默认值 | 说明 | | ----------- | --------------------------- | ------- | ---------------------------------- | | `fixed` | `'left' \| 'right' \| true` | - | 固定列位置;`true` 等同 `'left'`。 | | `resizable` | `boolean` | `false` | 是否可拖拽调整列宽。 | | `minWidth` | `number` | `50` | 拖拽调整时的最小列宽。 | | `maxWidth` | `number` | - | 拖拽调整时的最大列宽。 | ### 排序 | 字段 | 类型 | 默认值 | 说明 | | ------------------- | ------------------------------------------------------------- | ----------------------- | ------------------------------------------------------ | | `sorter` | [`ColumnSorter`](/guide/type-reference#columnsorter) | - | 开启排序;支持默认比较、自定义比较函数和多列排序对象。 | | `sortOrder` | [`SortOrder`](/guide/type-reference#sortorder) | - | 受控排序方向。 | | `defaultSortOrder` | [`SortOrder`](/guide/type-reference#sortorder) | - | 非受控默认排序方向,仅首次渲染生效。 | | `sortDirections` | `SortOrder[]` | `['ascend', 'descend']` | 当前列可用排序方向。 | | `showSorterTooltip` | `boolean` | 继承表级配置 | 列级别控制是否显示排序 tooltip。 | 表级 `sortDirections` 和 `showSorterTooltip` 可作为默认值;列级配置优先。 ### 筛选 | 字段 | 类型 | 默认值 | 说明 | | ----------------------------------- | -------------------------------------------------------------- | -------- | ------------------------------------------- | | `filters` | [`ColumnFilterItem[]`](/guide/type-reference#columnfilteritem) | - | 筛选菜单项;传入后表头显示筛选图标。 | | `onFilter` | `(value, record) => boolean` | - | 筛选函数,返回 `true` 表示该行匹配。 | | `filterMultiple` | `boolean` | `true` | 是否支持多选筛选。 | | `filteredValue` | `Array \| null` | - | 受控筛选值。 | | `defaultFilteredValue` | `Array` | - | 非受控默认筛选值。 | | `customFilterDropdown` | `boolean` | `false` | 使用表级 `customFilterDropdown` slot。 | | `filterSearch` | `boolean \| (input, filter) => boolean` | `false` | 筛选项搜索。 | | `filterMode` | `'menu' \| 'tree'` | `'menu'` | 筛选项展示模式。 | | `filterResetToDefaultFilteredValue` | `boolean` | `false` | 重置时恢复到默认筛选值。 | | `filterDropdownOpen` | `boolean` | - | 受控筛选下拉可见性。 | | `onFilterDropdownOpenChange` | `(visible) => void` | - | 筛选下拉可见性变化回调。 | | `filtered` | `boolean` | - | 外部控制筛选图标高亮状态,不改变筛选逻辑。 | | `filterIcon` | `({ filtered }) => VNodeChild` | - | 自定义筛选图标。 | | `filterDropdown` | `VNodeChild \| (props) => VNodeChild` | - | 列级别自定义筛选面板,优先级高于表级 slot。 | ### 多级表头 | 字段 | 类型 | 默认值 | 说明 | | ---------- | -------------------------------------------------------- | ------ | ------------------------------------------ | | `children` | `Array \| ColumnGroupType>` | - | 子列配置。存在 `children` 时该列作为列组。 | 列组不会接收排序、筛选、`dataIndex` 和 `customRender` 等叶子列行为。 ## Row Selection `rowSelection` 开启选择列,支持多选、单选、树形联动、批量选择菜单和受控选中状态。 | 字段 | 类型 | 默认值 | 说明 | | ------------------------- | ------------------------------------------------------------------ | ------------ | ------------------------------ | | `type` | `'checkbox' \| 'radio'` | `'checkbox'` | 选择类型。 | | `selectedRowKeys` | `Key[]` | - | 受控选中 key。 | | `defaultSelectedRowKeys` | `Key[]` | - | 默认选中 key。 | | `onChange` | `(keys, rows) => void` | - | 选中项变化回调。 | | `onSelect` | `(record, selected, rows) => void` | - | 单行选择变化回调。 | | `onSelectMultiple` | `(selected, rows, changeRows) => void` | - | Shift 多选变化回调。 | | `onSelectAll` | `(selected, rows, changeRows) => void` | - | 全选变化回调。 | | `onSelectInvert` | `(keys) => void` | - | 反选回调。 | | `onSelectNone` | `() => void` | - | 清空选择回调。 | | `getCheckboxProps` | `(record) => { disabled?, name? }` | - | 为选择控件注入属性。 | | `columnWidth` | `number \| string` | - | 选择列宽度。 | | `fixed` | `boolean \| 'left' \| 'right'` | - | 选择列固定位置。 | | `columnTitle` | `string \| VNodeChild` | - | 选择列表头内容。 | | `renderCell` | `(value, record, index, originNode) => VNodeChild \| RenderedCell` | - | 自定义选择单元格。 | | `checkStrictly` | `boolean` | `true` | 树形数据是否父子独立选择。 | | `selections` | `boolean \| array` | `false` | 默认或自定义批量选择菜单。 | | `hideSelectAll` | `boolean` | `false` | 隐藏全选 checkbox 和选择下拉。 | | `preserveSelectedRowKeys` | `boolean` | `false` | 数据源变化时保留已选 key。 | 默认批量选择常量见 [SelectionSentinel](/guide/type-reference#selectionsentinel)。 ## Expandable `expandable` 用于展开行内容。树形数据的展开 props 在 `VTable` 顶层配置。 | 字段 | 类型 | 默认值 | 说明 | | ------------------------ | ------------------------------------------------- | ------- | -------------------------------------- | | `expandedRowRender` | `(record, index, indent, expanded) => VNodeChild` | - | 展开行内容渲染函数。 | | `expandedRowKeys` | `Key[]` | - | 受控展开行 key。 | | `defaultExpandedRowKeys` | `Key[]` | - | 默认展开行 key。 | | `expandRowByClick` | `boolean` | `false` | 点击整行展开。 | | `expandIcon` | `(props) => VNodeChild` | - | 自定义展开图标。 | | `onExpand` | `(expanded, record) => void` | - | 展开/折叠回调。 | | `onExpandedRowsChange` | `(expandedKeys) => void` | - | 展开 key 变化回调。 | | `columnWidth` | `number \| string` | - | 展开列宽度。 | | `fixed` | `'left' \| 'right' \| true` | - | 展开列固定位置;`true` 等同 `'left'`。 | | `defaultExpandAllRows` | `boolean` | `false` | 默认展开所有行。 | | `rowExpandable` | `(record) => boolean` | - | 判断某行是否可展开。 | | `showExpandColumn` | `boolean` | `true` | 是否显示展开列。 | | `expandedRowClassName` | `string \| RowClassName` | - | 展开行 class。 | ## Events | 事件 | 参数 | 说明 | | -------------- | -------------------------- | ------------------------------------------------------------------------ | | `change` | `(filters, sorter, extra)` | 排序、筛选、选择后的统一事件出口。 | | `resizeColumn` | `(column, width)` | 拖拽列宽结束后触发。 | | `rowDragEnd` | `(newData, info)` | 行拖拽排序结束且顺序有变化时触发,见[行拖拽排序](/guide/row-drag-sort)。 | `change` 当前不包含 pagination 参数。`extra.action` 取值为 `'sort'`、`'filter'` 或 `'select'`。 ```ts function handleChange(filters, sorter, extra) { if (extra.action === 'sort') { // sync sort state or request remote data } } ``` ## Slots | Slot | 参数类型 | 说明 | | ---------------------- | ----------------------------------------------------------------------------------------------- | ---------------------- | | `bodyCell` | [`TableBodyCellSlotProps`](/guide/type-reference#tablebodycellslotprops) | 自定义单元格内容。 | | `headerCell` | [`TableHeaderCellSlotProps`](/guide/type-reference#tableheadercellslotprops) | 自定义表头单元格内容。 | | `empty` | `()` | 自定义空状态。 | | `loading` | `()` | 自定义加载态。 | | `customFilterDropdown` | [`CustomFilterDropdownSlotProps`](/guide/type-reference#customfilterdropdownslotprops) | 表级自定义筛选面板。 | | `customFilterIcon` | `{ column, filtered }` | 表级自定义筛选图标。 | | `title` | [`TableDataSlotProps`](/guide/type-reference#tabledataslotprops) | 自定义标题区域。 | | `footer` | [`TableDataSlotProps`](/guide/type-reference#tabledataslotprops) | 自定义页脚区域。 | | `summary` | `()` | 自定义摘要区域。 | > 这里列的是 Vue slots。若要通过 class 覆盖结构样式,请查看 [ui Slot 参考](/guide/ui-slots-reference)。 ## VTableSummary `VTableSummary` 用于摘要行。 | 组件 | 常用字段 | 说明 | | -------------------- | -------------------------------------- | ---------------------------------------------------- | | `VTableSummary` | `fixed` | 摘要容器;`fixed` 支持 `true`、`'top'`、`'bottom'`。 | | `VTableSummary.Row` | - | 摘要行。 | | `VTableSummary.Cell` | `index`、`colSpan`、`rowSpan`、`align` | 摘要单元格。 | ## 相关页面 - [类型参考](/guide/type-reference) - [ui Slot 参考](/guide/ui-slots-reference) - [排序](/guide/sorting) - [筛选](/guide/filtering) --- # 自定义行与插槽 这部分能力用于把表格接进更复杂的业务界面。 当默认列渲染已经不够,但你又不想放弃排序、筛选、对齐和主题系统时,customRow、customHeaderRow、headerCell、bodyCell 和 summary 这些入口会更合适。 ## 在线示例 `headerCell` 改表头文案、`bodyCell` 把状态换成徽标、`customRow` 给整行挂点击事件。 ```vue // @/demos/api-wiring-and-slots/basic.vue ``` ## 常见入口 ```vue ``` ## 每个入口适合做什么 - rowClassName,根据行数据返回 class。 - customRow,给某一行注入属性、事件和 style。 - customHeaderRow,给表头行注入属性。 - customHeaderCell,给表头单元格补充属性。 - headerCell / bodyCell,替换单元格内部内容,同时保留表格内部交互能力。 - summary,在表体后追加摘要区域。 ## 什么时候该用 ui,什么时候该用 slot - 只是改样式,优先用 ui 和主题覆盖。 - 需要改内容结构或注入业务事件,再使用插槽和 customRow。 - 需要按记录动态附加属性时,优先用 customRow,而不是操作 DOM。 ## 使用建议 - 结构级扩展尽量通过组件提供的入口完成,不要在 mounted 后再手动查 DOM 改写。 - bodyCell 更适合做状态标签、图标、补充文案等内容级增强。 - 单元格或整行编辑也通过 bodyCell 组合;草稿、校验和提交由业务管理,完整示例见[编辑](/guide/editing)。 - 如果同一类样式会反复出现,优先沉淀到主题和 ui,而不是在每张表里重复写 slot 模板。 ## 相关页面 - [三层主题覆盖](/guide/theme-overrides) - [标题、页脚与摘要行](/guide/title-footer-summary) - [编辑](/guide/editing) --- # 为什么这样设计 这一页是可选参考,不是大多数使用者的必读内容。 如果你只是想把表格接进项目,优先看快速开始、迁移、功能页和 API 就够了。只有在你要评估长期采用、做二次封装或统一主题治理时,这一页才值得读。 ## 1. 为什么公开接入入口保持单一 对使用者来说,最重要的是安装、导入和升级路径足够稳定,所以 vtable-guild 对外只保留一个接入入口: - `@vtable-guild/vtable-guild` - `createVTableGuild` 作为全局配置入口,用来切预设、语言和全局主题 仓库内部仍然按职责组织源码模块,但这些模块是实现细节,不需要由使用者理解或分别安装。这样做的价值是: - 安装路径简单,不需要判断该装哪些包 - 类型链更短,主题覆盖和组件类型只围绕一个入口 - 版本心智更清晰,升级时只关注一个包 ## 2. 为什么主题要做成三层 如果主题只有一层,通常会出现两个问题: - 全局改起来太重,单页不好做例外。 - 单页改起来太散,最后全是业务样式补丁。 vtable-guild 把主题拆成三层,就是为了解决这个问题: 1. 预设负责整体视觉基线。 2. createVTableGuild 的全局 theme 负责应用级统一覆盖。 3. 实例 ui 负责单张表格的局部调整。 这意味着你既能快速接入 antdv 或 element-plus 风格,也能只改一张表的表头、单元格或根容器样式,而不必复制整套主题。 ## 3. 为什么它适合从现有表格迁移 VTable 的思路不是让你重新学习一套完全不同的表格模型,而是把常见能力继续留在 columns 和 props 里: - 排序、筛选、选择、树形和展开行都通过声明式配置组合。 - 虚拟滚动、列宽拖拽和主题覆盖作为增强能力直接叠加。 - 原本散在业务页面里的很多交互和样式补丁,可以回收到表格本体上。 这也是它适合替换现有业务表格的原因。你迁移的重点更多是确认边界,而不是整页推倒重写。 ## 什么时候值得看这页 下面这些情况再回来看就够了: - 你在评估是否长期采用 vtable-guild。 - 你要做企业内部二次封装。 - 你要统一多条业务线的表格主题。 - 你想理解为什么 themePreset、theme 和 ui 要分开使用。 ## 相关页面 - [为什么选择 vtable-guild](/guide/why) - [三层主题覆盖](/guide/theme-overrides) - [API Reference](/guide/api-reference) --- # 列显示与列顺序 「列设置」是最常见的列管理诉求:让用户勾选想看的列、按自己的习惯排列字段顺序。VTable 把这两件事拆成两个受控属性——列级 `visible` 控制是否显示,表级 `columnOrder` 控制显示顺序, 显示状态本身由你的应用持有(便于持久化到 localStorage 或用户偏好)。 ## 在线示例 用勾选框切换列的显隐,用 ‹ › 按钮调整列顺序。 ```vue // @/demos/column-display/basic.vue ``` ## 列显示 visible 在列上设置 `visible: false`,该列从表头和表体中移除。它是受控属性:显示与否完全由外部 字段决定,需要恢复显示时把 `visible` 改回来(或删掉这个字段)即可。 ```ts const columns: TableColumnsType = [ { title: '姓名', dataIndex: 'name', key: 'name', width: 180 }, // 用户在「列设置」里取消勾选了这一列 { title: '年龄', dataIndex: 'age', key: 'age', width: 96, visible: false }, { title: '状态', dataIndex: 'status', key: 'status', width: 140 }, ] ``` 关键行为: - 隐藏只作用于显示层。列上已激活的排序/筛选状态**不会**被丢弃——隐藏一个正在排序的列, 行序仍受它影响;重新显示后排序依旧生效。 - 分组列 `visible: false` 时整组隐藏;组内子列全部被隐藏时,整个空组也会被移除。 - 可以与 `responsive` 组合:两者任一不满足,列都不显示。 ## 列顺序 columnOrder `columnOrder` 是一个 key 数组,表达列的显示顺序: ```vue ``` 上面的配置下,列的渲染顺序为 `status → name → age`(若 `columns` 里还有未提到的列): - 在 `columnOrder` 中出现的列按数组顺序排前;同一 key 重复出现时取首次位置。 - 未出现的列(含无 key 列)保持原相对顺序,排在已匹配列之后。 - 选择列 / 展开列不参与顺序匹配,固定在行首。 - 只重排顶层列:分组列整组移动,不支持把子列移出分组。 ## 已知边界 - 重排可能破坏「左固定列连成前缀、右固定列连成后缀」的结构。非虚拟模式下 sticky 固定列 仍正常工作,但穿插排列时固定列阴影可能出现异常;开启 `virtualColumn` 横向虚拟化时, 不满足结构会有 dev 告警并回落为渲染全部列。 - 列宽拖拽的宽度覆写按列 key 记录,重排后自动保留。 ## 相关页面 - [列宽拖拽](/guide/column-resize) - [固定列](/guide/fixed-columns) - [API 参考](/guide/api-reference) --- # 列宽拖拽 列宽拖拽适合字段很多、内容长短差异大、用户希望现场微调布局的业务表格。它延续了接近 ant-design-vue 的字段心智,但作为内建能力提供。 ## 在线示例 把鼠标移到表头分隔线上左右拖动。「分类」列限制在 100–280px 之间,`resizeColumn` 事件把新宽度回写到列配置。 ```vue // @/demos/column-resize/basic.vue ``` ## 基础示例 在列上设置 `resizable: true` 即可。`width` 可以是像素数值、`auto`、百分比等 CSS 宽度,也可以省略。需要限制拖拽范围时,再补上 `minWidth` 和 `maxWidth`。 ```vue ``` ## 关键行为 - 只有 `resizable: true` 的列会显示拖拽手柄 - `width` 是数字时,拖拽从该数值开始;`width` 是 `auto`、百分比等非数字值或未设置时,拖拽从表头单元格的实际渲染宽度开始,不会发生起点跳变 - 拖拽过程中会实时更新列宽 - 拖拽结束时会触发 `resizeColumn` 事件,参数顺序为 `(column, width)`;其中 `width` 是调整后的像素数值,适合直接回写到列配置 - 未显式设置 `minWidth` 时,默认下限是 `50` ## 什么时候用 - 运维后台、报表页面或数据看板里字段很多 - 用户希望自己微调列宽,并把宽度持久化 - 你原本只能靠 CSS 或第三方拖拽库去拼列宽调整 ## 相关页面 - [固定列](/guide/fixed-columns) - [功能对比总览](/comparison/) --- # 编辑 vtable-guild 通过 `bodyCell` 插槽支持单元格编辑和整行编辑。表格负责稳定地渲染列、行与单元格,业务代码负责草稿、校验和提交,这样编辑器可以直接使用项目里已有的表单控件。 ## 单元格编辑 点击任意单元格进入编辑。输入内容先留在独立草稿中,按 Enter 或移开焦点提交,按 Escape 放弃。Enter 处理会避开输入法的候选词阶段。 ```vue // @/demos/editing/cell.vue ``` 示例里的编辑状态由稳定的 `rowKey` 和列的 `dataIndex` 共同定位。点击“倒序并替换数据”会创建新的记录对象并调整顺序,正在编辑的单元格仍会跟随同一条记录,不会因为行索引变化而串行。 输入框维护本地 draft,不会在每次输入时直接改写 `dataSource`。这对表格重渲染尤其重要,可以避免输入过程中编辑器反复更新导致光标跳动。 ## 整行编辑 整行编辑在进入编辑时复制一份行级草稿。多个字段修改完成后由“保存”一次性写回;“取消”只清理草稿,不会污染源记录。 ```vue // @/demos/editing/row.vue ``` 示例使用原生 `input` 和 `select`,因此可以同时运行在文档站和源码 Playground。实际项目里可原位替换成 `a-input`、`el-input`、Select、DatePicker 或已有的表单字段组件,表格不限制编辑器类型。 ## 实现原则 - 始终设置 `row-key="key"`,并按稳定行键保存编辑状态,不要使用渲染时的行索引。 - 用 `dataIndex` 标识字段;提交时用行键查找记录,即使数据重排或替换也不会写到另一行。 - 单元格输入先写本地 draft,只在 Enter 或 blur 时提交到 `dataSource`。 - Enter 事件同时检查 `event.isComposing` 和 composition 状态,避免中文输入法选词时提前保存。 - 整行编辑复制记录形成草稿,Save 时整体提交,Cancel 时直接丢弃。 ## 能力边界 `bodyCell` 已经能承载单元格编辑和整行编辑,但 vtable-guild 当前不内置以下能力: - 编辑状态管理和表单校验协议。 - 事务提交、撤销历史或服务端保存流程。 - Excel 式方向键、Tab 连续编辑和单元格选区。 如果这些能力是核心需求,建议在 `bodyCell` 上组合项目现有的表单方案;需要完整电子表格式编辑引擎时,vxe-table 等功能更完整的方案会更合适。 ## 虚拟滚动 虚拟滚动只保留可视区附近的行。编辑中的单元格离开可视区后,编辑器组件可能被卸载;草稿只要按稳定行键存储就不会串到其他记录,但业务仍需明确离屏时是自动提交、取消,还是保留草稿等待该行再次出现。 ## 相关页面 - [自定义行与插槽](/guide/api-wiring-and-slots) - [虚拟滚动](/guide/virtualization) - [API Reference](/guide/api-reference) --- # 展开行 展开行适合在不跳转详情页的前提下,直接在当前表格里展示补充信息。它和树形表格不是同一类能力:树形表格处理的是数据天然分层,展开行处理的是“当前行需要额外展开一块内容”。 ## 在线示例 `defaultExpandedRowKeys` 预展开第一行;第三行被 `rowExpandable` 判定为不可展开,不显示展开图标。 ```vue // @/demos/expandable-rows/basic.vue ``` ## 基础示例 ```vue ``` ## 常见扩展点 - `expandRowByClick` 整行点击展开 - `rowExpandable(record)` 按业务条件决定哪些行可展开 - `expandIcon(props)` 自定义展开图标 - `showExpandColumn: false` 隐藏独立展开列,只保留行点击展开 ## 什么时候用 - 行内详情预览 - 补充说明、标签、备注信息 - 内容明显超出单元格承载范围,但又不值得单独跳转详情页 ## 已知限制 - **不支持 preserve-expanded-content**:收起行时,展开内容会从 DOM 中销毁,再次展开时重新渲染。element-plus 原版 Table(2.9.7+)提供了 `preserve-expanded-content` 属性来保留已展开内容的 DOM 状态,当前 vtable-guild 尚未实现该能力。如果展开内容包含表单或有状态组件,收起后状态会丢失。 ## 相关页面 - [树形表格](/guide/tree-table) - [自定义行与插槽](/guide/api-wiring-and-slots) - [API Reference](/guide/api-reference) - [类型参考](/guide/type-reference) --- # 筛选 筛选能力由列上的 filters、onFilter、filteredValue、defaultFilteredValue 以及筛选面板配置共同组成。 对使用者来说,最重要的是先区分两种模式:一类是组件内部维护状态,另一类是页面外部完全受控。 ## 在线示例 多选筛选、单选筛选(`filterMultiple: false`)、带搜索框的筛选(`filterSearch`)和默认筛选值同时出现在一张表里。 ```vue // @/demos/filtering/basic.vue ``` ## 基础示例 ```vue ``` ## 受控与非受控 - defaultFilteredValue 只在首次渲染时生效,适合简单默认筛选。 - filteredValue 表示当前列进入受控模式,筛选状态完全由外部管理。 - filterResetToDefaultFilteredValue 用于控制“重置”后是否回到默认值,而不是直接清空。 ## 筛选组合规则 - 同一列里选中多个值时,是 OR 关系。 - 不同列之间是 AND 关系。 - change 事件会返回当前所有列的 filters 快照,适合做查询条件同步。 ## 自定义筛选面板 如果默认筛选面板不够用,可以选择两种扩展方式: - customFilterDropdown,走表级插槽统一接管。 - filterDropdown,在单列上直接定义自定义面板。 除此之外,你还可以使用: - filterSearch,为筛选项增加搜索能力。 - filterMode: 'tree',把筛选项渲染成树形结构。 ## 什么时候用受控模式 以下场景建议直接用 filteredValue: - 筛选条件需要同步到 URL。 - 页面查询由接口驱动,表格只负责展示当前结果。 - 多个筛选控件之间需要互相联动。 ## 相关页面 - [排序](/guide/sorting) - [API Reference](/guide/api-reference) - [类型参考](/guide/type-reference) --- # 固定列 固定列适合字段很多、横向滚动明显的宽表。它依赖两部分同时成立: - 表格提供 `scroll.x`,形成横向滚动区 - 需要固定的列声明 `fixed: 'left'` 或 `fixed: 'right'`;`fixed: true` 是 `fixed: 'left'` 的简写(与 ant-design-vue 对齐) ## 在线示例 九列宽表,左侧两列与右侧「状态」列固定。横向拖动滚动条看固定效果与阴影。 ```vue // @/demos/fixed-columns/basic.vue ``` ## 基础示例 ```vue ``` ## 常见组合 - 固定列 + 横向滚动 - 固定列 + 固定表头 - 固定列 + 行选择 / 展开列 ## 关键边界 - 固定列最好显式提供 `width`,否则 `sticky` 布局更容易出现错位 - 如果还有多级表头,建议保持列宽稳定,必要时使用 `tableLayout="fixed"` - 固定列和列宽拖拽可以组合,但优先保证固定列的宽度边界稳定 ## 什么时候用 - 用户需要一边横向滚动,一边保留关键主列 - 表格同时存在状态列、操作列和大量内容列 - 页面不适合拆成多张表,但横向信息量很高 ## 相关页面 - [列宽拖拽](/guide/column-resize) - [虚拟滚动](/guide/virtualization) --- # 快速开始 这一页只解决一件事:让你在已有 Vue 3 + Vite 项目里尽快跑起第一张 vtable-guild 表格。 如果你已经在使用 ant-design-vue 或 element-plus,建议先按这里完成初始化,再根据项目情况阅读迁移与主题页面。 ## 环境要求 - Node `^20.19.0` 或 `>=22.12.0` - pnpm `>=10.28.0` - Vue `^3.5.0` - Vite `^5` 或更高版本 ## 安装 组件本身不要求宿主项目安装 Tailwind CSS。先安装组件包: ```bash pnpm add @vtable-guild/vtable-guild ``` ## 配置样式入口 vtable-guild 支持 `prebuilt`、`tailwind3` 和 `tailwind4` 三种样式模式。 ### prebuilt 项目不使用 Tailwind CSS 时,直接引入完整预编译样式入口。 例如 `src/main.css`: ```css @import '@vtable-guild/vtable-guild/css/style'; ``` 这个入口已经预生成组件库内部需要的 utilities,使用它时不需要安装 Tailwind CSS、配置 `@tailwindcss/vite` 或扫描本库源码。 ### tailwind3 项目使用 Tailwind CSS 3 时,使用 Tailwind 3 入口,并在 Tailwind 配置中加入组件库 preset: ```js import vtableGuildTailwind3Preset from '@vtable-guild/vtable-guild/tailwind3-preset' export default { content: [ './index.html', './src/**/*.{vue,ts,tsx,js,jsx}', './node_modules/@vtable-guild/**/*.{js,mjs}', ], presets: [vtableGuildTailwind3Preset], } ``` ```css @import '@vtable-guild/vtable-guild/css/tailwind3'; @tailwind base; @tailwind components; @tailwind utilities; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind3' })) ``` ### tailwind4 项目使用 Tailwind CSS 4 时,使用 Tailwind 4 入口: ```bash pnpm add -D tailwindcss @tailwindcss/vite ``` ```ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [vue(), tailwindcss()], }) ``` ```css @import 'tailwindcss'; @import '@vtable-guild/vtable-guild/css/tailwind4'; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind4' })) ``` `@vtable-guild/vtable-guild/css/style`、`@vtable-guild/vtable-guild/css/tailwind3` 和 `@vtable-guild/vtable-guild/css/tailwind4` 均已包含: - 默认的 `antdv` 预设 - `element-plus` 预设 - 主题 token - 组件运行所需的基础样式 切换预设不需要额外追加 CSS。 预编译模式下,库内部 utility class 会输出 `vtg-` 前缀。Tailwind 3/4 模式下,内部 class 保持无前缀。详细规则见 [包导入与样式](/guide/package-consumption)。 ## 初始化插件 在入口文件里引入全局样式并初始化插件。 例如 `src/main.ts`: ```ts import { createApp } from 'vue' import App from './App.vue' import { createVTableGuild } from '@vtable-guild/vtable-guild' import './main.css' const app = createApp(App) app.use(createVTableGuild()) app.mount('#app') ``` 默认预设是 `antdv`。如果你要切到 `element-plus` 风格,只需把 `themePreset` 设为 `element-plus`: ```ts app.use( createVTableGuild({ themePreset: 'element-plus', }), ) ``` ## 最小可用示例 ```vue ``` ## 下一步看什么 - 想评估替换成本,继续看 [从 ant-design-vue 迁移](/guide/migration-from-antd) - 想统一视觉体系,继续看 [三层主题覆盖](/guide/theme-overrides) 和 [Table CSS 变量参考](/guide/theme-tokens) - 想确认差异化能力,继续看 [功能对比总览](/comparison/) --- # 多级表头与单元格合并 这一组能力主要服务于报表类页面。简单数据表一般不需要它,但一旦表格开始承载指标分组、结构化汇总或复杂横向布局,它就会变得很重要。 ## 在线示例 三层嵌套表头,配合 `customCell` 返回的 `rowSpan` 纵向合并「区域」列。 ```vue // @/demos/grouped-and-merged-cells/basic.vue ``` ## 多级表头 多级表头通过 children 形成层级结构。 ```ts const columns = [ { title: '姓名', dataIndex: 'name', key: 'name', width: 160 }, { title: '画像信息', key: 'profile', children: [ { title: '年龄', dataIndex: 'age', key: 'age', width: 96 }, { title: '区域', dataIndex: 'region', key: 'region', width: 150 }, ], }, ] ``` ## 表体合并 表体合并主要通过两种方式完成: - customCell 返回 rowSpan 或 colSpan。 - customRender 返回带 props 的 RenderedCell。 ```ts const columns = [ { title: '组别', dataIndex: 'group', key: 'group', customCell: (_record, index) => { if (index === 0) return { rowSpan: 2 } if (index === 1) return { rowSpan: 0 } return {} }, }, { title: '姓名', dataIndex: 'name', key: 'name', customRender: ({ text, record, index }) => index === 4 ? { children: `${String(text)} / ${record.score}`, props: { colSpan: 2 }, } : String(text), }, ] ``` ## 使用边界 - 多级表头依赖相对稳定的列结构,建议提供清晰的 width。 - 单元格合并更适合静态报表和明确分组结构。 - 开启 virtual 后,不适合再做跨行合并,因为虚拟滚动只渲染可视区域行节点。 ## 使用建议 - 表格一旦同时叠加固定列、多级表头和合并单元格,先保证布局稳定,再叠加其他交互。 - 如果只是想强调某些单元格样式,不要急着用合并,优先考虑 ui、customRender 或 summary。 ## 合并单元格的 hover 行为 当表格开启 `hoverable`(默认为 `true`)时,hover 高亮会正确处理跨行合并的情况: - hover 任意一行时,该行所有单元格高亮,包括跨行合并单元格(即使它的起始行不在当前行)。 - hover 跨行合并单元格本身时,它所跨越的所有行都会整体高亮。 这与 ant-design-vue 的行为一致,通过 JS 区间重叠判断实现,不依赖 CSS group-hover。 ## 相关页面 - [标题与摘要行](/guide/title-footer-summary) - [固定列](/guide/fixed-columns) --- # 指南 这套文档面向已经在 Vue 3 项目中使用 ant-design-vue 或 element-plus 的开发者。重点不是介绍仓库如何开发,而是帮助你判断是否值得替换现有表格、如何接入现有项目,以及在高频场景里怎样使用 vtable-guild。 ## 建议阅读顺序 ### 如果你正在评估是否替换 1. 先看 [为什么选择 vtable-guild](/guide/why),确认它解决的是哪一类表格问题。 2. 再看 [功能对比总览](/comparison/),快速判断和现有表格方案的差异。 3. 如果你关心增强点,再看 [增强与独有能力](/comparison/enhancements)。 ### 如果你已经准备接入 1. 从 [快速开始](/guide/getting-started) 完成安装、样式引入和插件初始化。 2. 如果你已有 ant-design-vue Table,继续看 [从 ant-design-vue 迁移](/guide/migration-from-antd)。 3. 继续看 [安装与使用](/guide/installation),确认样式入口、主题预设和常见接入方式。 ### 如果你正在实现具体功能 - 数据交互: [排序](/guide/sorting)、[筛选](/guide/filtering)、[行选择](/guide/selection) - 数据层级: [展开行](/guide/expandable-rows)、[树形表格](/guide/tree-table) - 大表格体验: [固定列](/guide/fixed-columns)、[虚拟滚动](/guide/virtualization)、[列宽拖拽](/guide/column-resize) - 结构扩展: [多级表头与合并](/guide/grouped-and-merged-cells)、[标题与摘要行](/guide/title-footer-summary)、[自定义行与插槽](/guide/api-wiring-and-slots)、[编辑](/guide/editing) ### 如果你要统一视觉体系 1. 先看 [三层主题覆盖](/guide/theme-overrides),建立 `themePreset`、全局 `theme`、实例级 `ui` 的分工。 2. 再看 [Table CSS 变量参考](/guide/theme-tokens),确认哪些场景只需要改 token。 3. 然后看 [ui Slot 参考](/guide/ui-slots-reference),查完整 slot 和 variant 清单。 4. 最后看 [预设与语言](/guide/presets-and-locales),处理 preset 切换与 locale。 ### 如果你要理解设计取舍 - 想理解为什么主题要分层、为什么接入方式保持单一: 看 [为什么这样设计](/guide/architecture) - 想快速查字段名、事件、slot 和常用类型: 看 [API Reference](/guide/api-reference) 和 [类型参考](/guide/type-reference) --- # 安装与使用 这一页只回答三件事: - 安装什么 - 样式从哪里引入 - 初始化后最常见的全局配置怎么写 ## 安装 ```bash pnpm add @vtable-guild/vtable-guild vue ``` Tailwind CSS 不是必需依赖。使用 `tailwind3` 或 `tailwind4` 模式时,再安装对应版本的 Tailwind CSS。 Tailwind CSS 4: ```bash pnpm add -D tailwindcss @tailwindcss/vite ``` Tailwind CSS 3: ```bash pnpm add -D tailwindcss@^3.4.19 postcss autoprefixer ``` ## 运行时入口 在业务代码里,运行时 API 和组件都从同一个入口导入: ```ts import { createVTableGuild, VTable } from '@vtable-guild/vtable-guild' ``` ## 样式入口 ::: code-group ```css [使用 Tailwind CSS 3] @import '@vtable-guild/vtable-guild/css/tailwind3'; @tailwind base; @tailwind components; @tailwind utilities; ``` ```css [使用 Tailwind CSS 4] @layer antd-reset, theme, base, components, utilities; @import 'ant-design-vue/dist/reset.css' layer(antd-reset); @import 'tailwindcss'; @import '@vtable-guild/vtable-guild/css/tailwind4'; ``` ```css [不使用 Tailwind CSS] @import 'ant-design-vue/dist/reset.css'; @import '@vtable-guild/vtable-guild/css/style'; ``` ::: `@vtable-guild/vtable-guild/css/style`、`@vtable-guild/vtable-guild/css/tailwind3` 和 `@vtable-guild/vtable-guild/css/tailwind4` 均已包含: - 默认 `antdv` 预设样式 - `element-plus` 预设样式 - 主题 token - 组件运行所需的基础 CSS 切换预设时不需要额外再导入其他 CSS。 `@vtable-guild/vtable-guild/css/style` 对应 `prebuilt` 模式。宿主项目不需要安装 Tailwind CSS,不需要配置 Tailwind 插件,也不需要扫描本库源码。 `@vtable-guild/vtable-guild/css/tailwind3` 对应 `tailwind3` 模式。Tailwind 配置需要加入 `@vtable-guild/vtable-guild/tailwind3-preset`,扫描 `node_modules/@vtable-guild`,并在插件层启用 `cssMode: 'tailwind3'`。 `@vtable-guild/vtable-guild/css/tailwind4` 对应 `tailwind4` 模式。使用它时,需要在插件层启用 `cssMode: 'tailwind4'`,内部 utility 会保持无前缀,方便宿主项目用普通 Tailwind class 覆盖。 ## 与 unlayered CSS reset 共存 ::: warning 必读:与 ant-design-vue / normalize.css 等 reset 共存(Tailwind CSS 4) 本库基于 Tailwind v4,所有 utility 都生成在 `@layer utilities` 内。按 [CSS Cascade Layers 规范](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer),**unlayered(未进任何层)的普通 CSS 规则会胜过任何 layer 内的规则**,与特异性无关。 ::: ::: tip prebuilt 用户 如果使用 `@vtable-guild/vtable-guild/css/style`,无需配置 Tailwind CSS 的 cascade layer。直接按上方的样式入口顺序引入即可。 ::: 如果项目里同时引入了未分层的全局 reset,例如: - `ant-design-vue/dist/reset.css` - `normalize.css` - 任何手写的全局 reset 它们里面诸如 `button { color: inherit }`、`input { ... }` 之类的规则会**压住**本库 Button、Input 等组件依赖的 Tailwind utility。典型症状:筛选弹窗里「重置 / 确定」按钮的文字颜色看上去是 ant-design-vue 的全局 `rgba(0,0,0,0.88)`,而不是预期的主色 / 白色。 ### 正确接法 用 `@import` 的 `layer()` 修饰符把 reset 显式收进一个比 `utilities` 更早的 layer,并在最前面**先声明 layer 顺序**: ```css @layer antd-reset, theme, base, components, utilities; @import 'ant-design-vue/dist/reset.css' layer(antd-reset); @import 'tailwindcss'; @import '@vtable-guild/vtable-guild/css/tailwind4'; ``` 要点: - `@layer name1, name2, ...;` 声明必须出现在所有 `@import` 之前,否则顺序无效。 - `antd-reset` 写在 `utilities` 之前,意味着 utilities 优先级更高,能盖掉 reset 里的元素级规则。 - **同时把 `main.ts` 里类似 `import 'ant-design-vue/dist/reset.css'` 的 JS 侧副作用 import 删掉**,统一交给 CSS 侧的 `@import ... layer(...)` 管理。JS 侧 import 的 CSS 会绕过 `layer()`,再次回到 unlayered,问题就会复现。 - 同样的写法适用于 `normalize.css`、`element-plus/dist/index.css` 中未分层的部分等:把它们都按相同模式收进自定义 layer。 ## 插件初始化 ```ts import { createApp } from 'vue' import App from './App.vue' import { createVTableGuild } from '@vtable-guild/vtable-guild' import './main.css' const app = createApp(App) app.use( createVTableGuild({ themePreset: 'antdv', // 如果使用 @vtable-guild/vtable-guild/css/tailwind3,请设置 cssMode: 'tailwind3' // 如果使用 @vtable-guild/vtable-guild/css/tailwind4,请设置 cssMode: 'tailwind4' }), ) app.mount('#app') ``` ## 常用全局配置 `createVTableGuild` 常见配置包括: - `themePreset` 切换 `antdv` 或 `element-plus` - `cssMode` 选择 `prebuilt`、`tailwind3` 或 `tailwind4` 样式模式 - `classPrefix` 预编译模式下的内部 utility class 前缀,默认 `vtg` - `theme` 全局主题覆盖 - `locale` 当前语言标识 - `locales` 自定义语言包注册表 - `localeOverrides` 当前语言包的局部覆盖 - `compatClass` 是否额外输出 `ant-table-*` 兼容类名,默认 `false`;用于让 antdv 时期的覆盖 CSS 继续生效, 详见[从 ant-design-vue 迁移](./migration-from-antd#保留旧的覆盖-css-兼容类名) 示例: ```ts app.use( createVTableGuild({ themePreset: 'antdv', cssMode: 'prebuilt', locale: 'zh-CN', theme: { table: { slots: { th: 'bg-slate-50 font-medium', }, defaultVariants: { size: 'small', }, }, }, }), ) ``` ## 视觉调整怎么选 - 想切整套视觉基线,用 `themePreset` - 想统一业务项目规则,用全局 `theme` - 想改单个实例,用 `ui` 和 `class` - 只想改颜色、尺寸、间距等 token,优先覆盖 CSS 变量 ## 单实例覆盖示例 ```vue ``` ## 继续阅读 - [快速开始](/guide/getting-started) - [三层主题覆盖](/guide/theme-overrides) - [ui Slot 参考](/guide/ui-slots-reference) - [Table CSS 变量参考](/guide/theme-tokens) - [预设与语言](/guide/presets-and-locales) ---

AI-READY DOCUMENTATION / VTABLE-GUILD

LLMs.txt

给 Cursor、Codex、Claude Code 等 AI 编码工具一条更短、更稳定的文档入口,让它们先理解 vtable-guild 的 API、边界和推荐用法,再开始生成代码。

自动生成 纯 Markdown 中文主导 · English partial
## 什么是 LLMs.txt? `llms.txt` 是给大语言模型和 AI 编码 Agent 使用的文档索引。它把站点中的中文文档、英文文档和完整文档入口整理成一份轻量文本,让工具可以快速判断应该读取哪些内容。 它不是新的组件 API,也不会改变 `vtable-guild` 的运行时行为;它只是把已有文档整理成更适合机器读取的入口。 ## 应该使用哪个文件? | 你的目标 | 推荐资源 | 原因 | | --------------------------------- | --------------------------------- | --------------------------------- | | 让 AI 快速了解项目能做什么 | [`llms.txt`](/llms.txt) | 内容短,包含文档索引和页面描述 | | 生成具体的表格代码 | [`llms-full.txt`](/llms-full.txt) | 包含 props、slots、类型和限制说明 | | 排查虚拟滚动、树表或 summary 问题 | `llms-full.txt` + 对应功能页 | 能同时看到 API 和场景边界 | ## 在 AI 工具中使用 不同工具对外部文档的入口名称可能不同,但使用方式基本一致:把 `llms.txt` 作为项目文档或远程资料加入上下文;当任务需要完整 API 细节时,再补充 `llms-full.txt`。 ### Cursor 将下面的地址加入项目文档或远程资料: ```text https://parade0393.github.io/vtable-guild/llms.txt ``` 如果 AI 需要生成复杂的 `VTable` 配置,再让它读取: ```text https://parade0393.github.io/vtable-guild/llms-full.txt ``` ### Codex 在 Codex 的项目或任务上下文中加入下面的文档入口,让它在修改组件代码前先了解真实 API: ```text https://parade0393.github.io/vtable-guild/llms.txt ``` 需要完整 props、slots、类型和边界说明时,再补充 `llms-full.txt`。建议同时要求 Codex: > 生成 vtable-guild 代码前,先参考项目中的 llms.txt;不要假设 ant-design-vue Table 尚未实现的 API 在 vtable-guild 中一定存在。 ### Claude Code 和其他 Agent 把 `llms-full.txt` 下载或加入项目上下文后,适合用于以下任务: - 根据现有 `columns` 和 `rowSelection` 生成迁移代码; - 判断 `virtual`、`virtualColumn`、固定列和 `scroll.y` 是否可以组合; - 根据运行时告警定位 `rowKey`、行高或虚拟化配置问题; - 查询 `VTableSummary`、展开行、树形数据和主题覆盖的写法。 ## 它是怎样生成的? 站点构建结束时会扫描 `site/` 下的 Markdown 页面,并把页面正文整理到构建产物目录: ```bash pnpm --filter @vtable-guild/site build ``` 生成结果为: ```text site/.vitepress/dist/llms.txt site/.vitepress/dist/llms-full.txt ``` 因此,文档页面更新后不需要手工维护这两个文件;重新构建并部署站点即可同步内容。 ## 给 Agent 的使用建议 1. 先读 `llms.txt`,确认文档范围和对应功能页。 2. 再读 `llms-full.txt` 或具体页面,确认真实 API 和限制。 3. 生成代码时显式配置稳定的 `rowKey`,不要凭经验补写未记录的 Table API。 4. 涉及虚拟滚动、树形数据、展开行或 summary 时,同时检查相关功能页的边界说明。
提示 这两个文件是机器友好的文档入口,不替代面向人的指南。想看完整示例和视觉行为,请继续从左侧功能文档或 Playground 开始。
## 相关页面 - [API Reference](/guide/api-reference) - [虚拟滚动](/guide/virtualization) - [树形表格](/guide/tree-table) - [标题、页脚与摘要行](/guide/title-footer-summary) - [完整 Agent API 参考](https://github.com/parade0393/vtable-guild/blob/master/docs/AGENT_API.md) --- # 从 ant-design-vue 迁移 这一页的目标不是宣称“完全兼容”,而是帮助你快速判断哪些表格页面可以低成本迁移,哪些地方需要明确调整。 ## 适合迁移的场景 如果你的页面主要依赖这些能力,迁移成本通常比较可控: - columns 列配置 - sorter 排序 - filters 筛选 - rowSelection 行选择 - expandable 展开行 - scroll 固定表头与横向滚动 - customRender、自定义行和常见插槽 ## 主要收益 - 保留熟悉的列定义方式和常见交互模型。 - 把虚拟滚动收敛到同一张表格里,并继续沿用熟悉的列宽控制写法。 - 用 striped、hoverable、ui 等一等能力替代业务层样式补丁。 - 把主题切换和局部覆写收敛到统一模型中。 ## 你需要注意的差异 ### 1. 不是所有 API 都完全一致 vtable-guild 的设计方向是兼容高频表格使用方式,而不是逐项复制 ant-design-vue Table 的全部接口。 最重要的已知差异是: - 当前没有内置 pagination。 - change 事件签名为 (filters, sorter, extra),不包含 ant-design-vue 里的 pagination 参数。 - resizeColumn 事件参数顺序为 (column, width),而 ant-design-vue 文档里的顺序是 (width, column)。 下列以前需要调整、现在已与 ant-design-vue 完全对齐,可直接迁移: - `column.fixed: true` 等同 `'left'` - `loading` 接受 `boolean` 或 `{ spinning?, indicator?, tip? }` 对象 - `column.ellipsis` 接受 `boolean` 或 `{ showTitle?: boolean }` - `size` 三档命名为 `small` / `middle` / `large` ## 常见映射 | ant-design-vue | vtable-guild | | ------------------------------------------------------- | ------------------------------------------------------------- | | bordered | bordered | | rowSelection | rowSelection | | expandable | expandable | | scroll.x / scroll.y | scroll.x / scroll.y | | sorter / sortOrder / defaultSortOrder | sorter / sortOrder / defaultSortOrder | | filters / onFilter | filters / onFilter | | pagination / change(pagination, filters, sorter, extra) | 分页自行在页面层处理;change 为 (filters, sorter, extra) | | rowClassName 实现斑马纹 | 优先改用 striped | | 自行关闭 hover 效果 | 优先改用 hoverable | | resizable / minWidth / maxWidth | 继续使用同名字段;resizeColumn 事件参数顺序为 (column, width) | ## 保留旧的覆盖 CSS(兼容类名) 如果页面里已经写了一批 `.ant-table-thead > tr > th { ... }`、`:deep(.ant-table-cell)` 这样的覆盖样式, 逐条重写成 Tailwind 或 `ui` prop 的成本很高。可以开启兼容类名,让 vtable-guild 在原有元素上 额外输出一套 `ant-table-*` 类,旧选择器继续命中: ```ts app.use( createVTableGuild({ compatClass: true, // 默认关闭 }), ) ``` 这是全局开关,只在安装时读取一次,不支持运行时切换。开启后不改变 DOM 结构,也不引入任何样式, 只是在既有元素上多加 class,所以视觉表现与关闭时完全一致。 覆盖范围包括结构类(`ant-table-wrapper`、`ant-table-thead`、`ant-table-cell` 等)、 变体类(`ant-table-small`、`ant-table-bordered`)以及状态类 (`ant-table-row-selected`、`ant-table-cell-fix-left-last`、`ant-table-row-level-{n}` 等)。 ### 与 ant-design-vue 共存时会串味吗 一般不会。ant-design-vue 4.x 默认通过 cssinjs 给每条规则的选择器注入 hash 类,实际产出形如: ```css .ant-table-wrapper.css-dev-only-do-not-override-xxxxx .ant-table-thead > tr > th { ... } ``` 我们的元素不带那个 hash 类,所以 **antdv 自己的样式匹配不到我们的表格**,而你手写的 `.ant-table-thead > tr > th` 能正常命中 —— 这正是需要的效果。 我们在同时加载 antdv 的页面上实测过:页面共有 178 条 `ant-table` 规则,命中我们表格元素的是 0 条。 ::: warning 例外 如果你的项目使用了 ``,antdv 不再生成 hash 类,选择器退化为 `[class^='ant-table']`、`.ant-table-wrapper .ant-table-cell` 这类形式,此时 antdv 的样式会真的 作用到我们的表格上 —— 同一个页面上实测有 20 条规则会命中。这种情况下不要开启兼容类名。 ::: ### 稳定性边界与写法建议 `compatClass` 开关本身是稳定 API。类名清单也保持向后兼容,删改会在 changelog 中明示。 不做承诺的是**类名之间的 DOM 结构关系**。我们会为性能继续调整 DOM —— 例如 2.5.0 删掉了虚拟滚动 的 per-row ``,宽表 DOM 节点数因此少了 40%。这类调整不会让类名消失,但会让依赖父子 关系的选择器失配。所以写覆盖 CSS 时,两种写法的抗变更能力差别很大: ```css /* 推荐:只依赖类名存在于元素上,DOM 怎么调整都命中 */ .ant-table-cell { padding: 4px 8px; } /* 脆:依赖 thead > tr > th 的层级关系,DOM 一调整就失配 */ .ant-table-thead > tr > th { padding: 4px 8px; } ``` 上面「保留旧的覆盖 CSS」一节举的 `.ant-table-thead > tr > th` 正是脆的那一类 —— 它能立刻跑起来, 但如果你有机会顺手改写,优先降成单类选择器。 ::: tip 兼容类名是迁移期的过渡辅助。长期仍建议迁移到 `ui` prop 或主题覆盖,那才是我们承诺稳定的定制入口。 ::: ## 推荐迁移顺序 1. 先迁移一张依赖排序、筛选、选择的常规业务表格。 2. 再把页面里的视觉补丁替换为 bordered、striped、hoverable 和 ui 覆盖。 3. 最后再启用 virtual、resizable 这类增强能力。 这种顺序更稳,因为你可以先验证交互兼容性,再逐步引入新的表格能力。 ## 一个简单的迁移思路 ### 原页面里通常已经有这些内容 - dataSource - columns - rowKey - onChange - 若干样式补丁和 rowClassName ### 迁移时优先做这几件事 1. 保留原有数据结构和 columns 定义。 2. 把表格组件替换为 VTable。 3. 检查 change 回调是否依赖 pagination 参数,如果依赖,需要先从页面逻辑中拆掉。 4. 把样式补丁中与条纹行、hover 行、边框相关的部分改成对应 props。 5. 如果页面监听过 resizeColumn,一并确认事件参数顺序是否需要调整。 6. 确认是否需要 virtual 或 resizable,再逐步开启。 ## 什么时候需要更谨慎 以下情况建议先做小范围验证: - 页面高度依赖 ant-design-vue Table 的分页行为。 - 你有很多深度定制的表头、筛选下拉或复杂联动逻辑。 - 页面已经围绕旧表格写了大量 CSS 选择器(可先开启[兼容类名](#保留旧的覆盖-css-兼容类名)过渡)。 这类页面不是不能迁移,而是更适合先通过 [API Reference](/guide/api-reference) 和功能页确认具体边界。 --- # 包导入与样式 这一页专门说明运行时入口、CSS 入口和 class 前缀策略。普通组件 API 不需要因为前缀策略变化而调整。 ## 运行时入口 组件和插件都从主入口导入: ```ts import { createVTableGuild, VTable } from '@vtable-guild/vtable-guild' ``` ## prebuilt 模式 宿主项目不使用 Tailwind CSS 时,使用完整预编译 CSS: ```css @import 'ant-design-vue/dist/reset.css'; @import '@vtable-guild/vtable-guild/css/style'; ``` ```ts app.use(createVTableGuild()) ``` 这是默认模式,也就是 `cssMode: 'prebuilt'`。库内部 utility class 会输出 `vtg-` 前缀,例如 `vtg-flex`、`vtg-px-1`,避免污染使用者项目或其他 UI 库的 class 空间。 用户传入的 class 不会被自动加前缀,包括: - `class` - `ui` - `rowClassName` - `customRow` - `customHeaderRow` - `customCell` / `customHeaderCell` 返回的 class ## 覆盖内部 utility 预编译模式下,如果你想覆盖库内部 utility,也应传同前缀: ```vue ``` 直接传 `px-2` 可能会和内部 `vtg-px-*` 同时存在,不保证覆盖内部样式。这个设计是刻意的:裸 class 保持为用户自己的 class,不由组件库重写语义。 ## 自定义前缀 可以通过 `classPrefix` 修改内部 utility 前缀: ```ts app.use( createVTableGuild({ classPrefix: 'app', }), ) ``` 这时运行时会输出 `app-*`。预编译 CSS 也必须使用同一个前缀生成: ```bash VTG_CLASS_PREFIX=app pnpm --filter @vtable-guild/vtable-guild copy-css ``` 如果前缀运行时和 CSS 产物不一致,样式不会命中。 ## tailwind3 模式 宿主项目使用 Tailwind CSS 3 构建 utility 时,使用 Tailwind 3 入口: ```js import vtableGuildTailwind3Preset from '@vtable-guild/vtable-guild/tailwind3-preset' export default { content: [ './index.html', './src/**/*.{vue,ts,tsx,js,jsx}', './node_modules/@vtable-guild/**/*.{js,mjs}', ], presets: [vtableGuildTailwind3Preset], } ``` ```css @import '@vtable-guild/vtable-guild/css/tailwind3'; @tailwind base; @tailwind components; @tailwind utilities; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind3' })) ``` Tailwind 3 模式下,库内部 class 保持无前缀,所以用户可以传普通 Tailwind class 覆盖内部 utility,例如: ```vue ``` ## tailwind4 模式 宿主项目使用 Tailwind CSS 4 构建 utility 时,使用 Tailwind 4 入口: ```css @layer antd-reset, theme, base, components, utilities; @import 'ant-design-vue/dist/reset.css' layer(antd-reset); @import 'tailwindcss'; @import '@vtable-guild/vtable-guild/css/tailwind4'; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind4' })) ``` Tailwind 4 模式下,库内部 class 保持无前缀,所以用户可以传普通 Tailwind class 覆盖内部 utility,例如: ```vue ``` ## CSS 入口 当前支持的 CSS 入口是 `css/style`、`css/tailwind3` 和 `css/tailwind4`,分别对应 `prebuilt`、`tailwind3` 和 `tailwind4`。 --- # 预设与语言 这部分配置解决的是两个更上层的问题: - 整体外观要贴近哪套 UI 体系。 - 表格内部文案要用哪种语言,以及如何局部覆盖。 ## 在线示例 同一套列定义与数据,切换预设与语言看效果。这是本库最独特的一点:换皮肤不用换表格、不用换 API。 ```vue // @/demos/presets-and-locales/preset-switch.vue ``` > 应用里一般直接 `createVTableGuild({ themePreset })` 配一次即可。上面的示例为了在同一页对比两套皮肤,才就地 provide 了一个作用域 context。 ## 主题预设 当前内置两套主题预设: - antdv,默认预设,适合已经接入 ant-design-vue 的项目。 - element-plus,适合已经使用 element-plus 视觉体系的项目。 运行时切换方式很直接: ```ts app.use( createVTableGuild({ themePreset: 'antdv', }), ) ``` 如果你改成 element-plus,直接在 JS 侧切换即可,无需追加 CSS(`@vtable-guild/vtable-guild/css/style`、`@vtable-guild/vtable-guild/css/tailwind3` 和 `@vtable-guild/vtable-guild/css/tailwind4` 均已内含所有预设样式): ```ts app.use( createVTableGuild({ themePreset: 'element-plus', }), ) ``` 你不需要手动在 HTML 上添加 `data-vtg-preset` 属性,插件会自动处理。更多接入方式见 [安装与使用](/guide/installation)。 ## 内置语言 当前内置的 preset locale 至少覆盖了 zh-CN 和 en-US 两种常见语言场景,主要包括: - 排序提示文案 - 筛选面板文案 - 空态文案 - 加载态文案 - 行选择菜单文案 ## 注册和覆盖语言包 如果你要切成英文或自定义文案,可以在插件层传 locale、locales 和 localeOverrides: ```ts app.use( createVTableGuild({ locale: 'en-US', locales: { 'en-US': { table: { header: { sortTriggerAsc: 'Sort ascending', sortTriggerDesc: 'Sort descending', cancelSort: 'Cancel sorting', filterTriggerAriaLabel: 'Filter', }, filterDropdown: { searchPlaceholder: 'Search filters', emptyText: 'No filters', resetText: 'Reset', confirmText: 'OK', selectAllText: 'Select all', }, empty: { text: 'No data' }, loading: { text: 'Loading...' }, selection: { selectAll: 'Select all', selectInvert: 'Invert selection', selectNone: 'Clear selection', }, }, }, }, }), ) ``` 如果你只想覆盖少量字段,优先使用 localeOverrides,不必重写整套 locale。 ## 局部作用域切换 当你需要在某个子树里单独切换预设或语言时,可以使用 VTableGuildConfigProvider: ```vue ``` 这类方式适合局部对照页、多语言后台或嵌入式业务模块。 ## 相关页面 - [三层主题覆盖](/guide/theme-overrides) - [安装与使用](/guide/installation) --- # 行拖拽排序 给表格开启 `rowDraggable`,行本身即可拖拽(原生 HTML5 拖放,无需引入第三方拖拽库)。 拖拽遵循受控数据流:组件不改动数据,拖放结束时通过 `rowDragEnd` 事件返回排好序的 新数组,由你更新 `dataSource`——数据始终只有一份来源。 ## 在线示例 按住任意一行上下拖动,放到目标行上半部分插入其上方、下半部分插入其下方。 ```vue // @/demos/row-drag-sort/basic.vue ``` ## 基础用法 ```vue ``` `rowDragEnd` 的参数: - `newData`:拖拽完成后的全量数据数组(基于当前 `dataSource` 搬移拖拽行得出)。 - `info`:`{ draggedKey, targetKey, orderedKeys }`,分别为拖拽行 key、放置目标行 key、 以及与 `newData` 对应的全量 key 顺序(树形数据按数据顺序递归包含子节点)。 ## 关键行为 - 顺序没有变化时(例如把行拖回原位)**不会**触发 `rowDragEnd`。 - 行级退出:`customRow` 返回 `draggable: false` 的行不参与拖拽——不可拖起、也不会成为 放置目标,其余行不受影响(适合置顶行、汇总行等固定行)。 - `rowKey` 必须能稳定取到行标识;未配置时会回退为行索引并触发 dev 告警,拖拽结果不可靠。 - 虚拟滚动(`virtual`)下同样可用:拖拽事件挂在每行上,与滚动不冲突。搬移结果按 rowKey 在 `dataSource` 上计算,不依赖可视窗口下标。注意**没有拖到容器边缘的自动滚动**——目标行尚未 渲染进窗口时拖不到它,需要先滚动到位再放置。 - 建议在没有激活排序/筛选时使用:显示顺序由 `dataSource → 筛选 → 排序` 管线推导, 拖拽改写的是数据源顺序,激活的排序会在下次渲染时重新生效。 - 树形数据采用**跨父移动**语义:拖到目标行前 / 后,插入到目标行的**同级位置**——目标是 根行就回到顶层,目标是某个父的子节点就成为该父的子节点;被拖节点自带整棵子树, 展开 / 选中状态按 rowKey 记录、重排后保留。带环防护:把节点拖进它自己的子树里 不会触发事件、不改动数据。 - 展开行内容(`expandedRowRender` 渲染出的 ``)不可拖拽。 - 拖拽期间行 hover 高亮自动抑制,避免干扰放置指示线。 ## 样式定制 拖拽态通过三个 ui slot 与一个 token 定制(两套预设均提供): ```vue ``` - `trDragging`:拖拽中的行(默认半透明)。 - `trDropAbove` / `trDropBelow`:放置目标行上/下边缘的指示线。 - `--vtg-table-row-drop-indicator-color`:指示线颜色。 ## 相关页面 - [排序](/guide/sorting) - [ui Slot 参考](/guide/ui-slots-reference) - [API 参考](/guide/api-reference) --- # 行选择 rowSelection 用来开启行选择列,并统一管理单选、多选、全选、自定义批量选择和树形联动行为。 如果你的页面有“批量操作”“勾选后侧边编辑”“按选中项导出”这类需求,这一组能力会是高频入口。 ## 在线示例 受控多选 + `getCheckboxProps` 禁用单行 + 表头「选择项」下拉(含一个自定义项)。 ```vue // @/demos/selection/basic.vue ``` ## 基础多选 ```vue ``` ## 受控选择 当选中项需要和页面状态、侧边栏操作区或接口请求保持同步时,建议直接使用受控模式。 ```ts import { computed, ref } from 'vue' import type { Key, RowSelection } from '@vtable-guild/vtable-guild' const selectedRowKeys = ref([]) const rowSelection = computed>(() => ({ type: 'checkbox', selectedRowKeys: selectedRowKeys.value, onChange: (keys) => { selectedRowKeys.value = [...keys] }, })) ``` ## 单选与批量选择 - type: 'radio' 时进入单选模式。 - selections: true 可以开启默认批量选择菜单。 - selections 也可以传入自定义菜单项,用于“只选当前结果”“只选可操作项”等业务动作。 - hideSelectAll 可以隐藏表头全选入口。 ## 树形数据联动 当 checkStrictly 为 false 时,父子节点会联动: - 选中所有子节点后,父节点自动选中。 - 只选中部分子节点时,父节点显示为半选。 - 点击父节点会递归切换整棵子树。 如果你的业务更强调“每一行独立选择”,把 checkStrictly 保持为 true 会更清晰。 ## 使用建议 - 需要长期保留选中结果时,使用 preserveSelectedRowKeys。 - 如果某些行不可操作,优先通过 getCheckboxProps 禁用,而不是在点击后再回滚状态。 - 树形联动适合权限树、组织架构和分组数据,不适合每行语义完全独立的表格。 ## 相关页面 - [树形表格](/guide/tree-table) - [API Reference](/guide/api-reference) - [类型参考](/guide/type-reference) --- # 排序 排序能力围绕这几个字段展开:sorter、sortOrder、defaultSortOrder 和 sortDirections。 如果你来自 ant-design-vue,这套写法会比较熟悉。区别在于 vtable-guild 更强调直接可用的列排序能力,并把排序结果统一收敛到 change 事件里。 ## 在线示例 单列、多列、自定义比较函数在同一张表里。点击表头切换排序,按住 Shift 叠加多列。 ```vue // @/demos/sorting/basic.vue ``` ## 你可以怎么开启排序 - sorter: true,使用默认比较规则。数字按数值排序,其他值按字符串比较。 - sorter: (a, b) => number,使用自定义比较函数。 - sorter: { multiple: number },启用多列排序并指定优先级。 - defaultSortOrder,在首次渲染时设置默认排序方向。 - sortOrder,进入受控模式,由外部状态决定当前排序方向。 ## 最常见的写法 ```vue ``` ## 受控排序 当排序状态需要和页面查询参数、服务端请求或外部状态同步时,使用受控模式更稳。 ```ts import { computed, ref } from 'vue' import type { SortOrder, TableColumnsType } from '@vtable-guild/vtable-guild' const scoreOrder = ref('ascend') const columns = computed>(() => [ { title: '姓名', dataIndex: 'name', key: 'name' }, { title: '分数', dataIndex: 'score', key: 'score', sorter: true, sortOrder: scoreOrder.value, }, ]) ``` 在这种模式下,点击表头后会通过 change 返回新的 sorter 结果,是否更新 sortOrder 由你自己决定。 ## 多列排序 当多个字段都需要参与排序时,使用 multiple 指定优先级。数值越大,优先级越高。 ```ts const columns = [ { title: '年龄', dataIndex: 'age', key: 'age', sorter: { multiple: 1 } }, { title: '团队', dataIndex: 'team', key: 'team', sorter: { multiple: 2 } }, { title: '分数', dataIndex: 'score', key: 'score', sorter: { multiple: 3 } }, ] ``` ## 实际使用建议 - 简单排序优先用 sorter: true,避免为普通数字和字符串字段重复写比较函数。 - 如果页面还有筛选,当前数据处理顺序是先筛选再排序,多列排序会基于筛选后的结果运行。 - 如果你打算和服务端联动,建议从一开始就用受控模式,减少前后端状态不一致的问题。 ## 相关页面 - [筛选](/guide/filtering) - [API Reference](/guide/api-reference) - [类型参考](/guide/type-reference) --- # 三层主题覆盖 vtable-guild 的主题系统分成三层,目的是把“预设基线”“应用级统一规范”和“单实例例外”拆开管理,而不是把所有样式都写进页面里的选择器。 ## 三层结构 主题从低到高分成三层: 1. 预设默认主题 当前内置 `antdv` 和 `element-plus` 两套视觉基线,通过 `themePreset` 切换。 2. `createVTableGuild` 的全局 `theme` 适合整个应用统一表头、边框、hover、默认 size 等规则。 3. `VTable` 实例上的 `ui` 和 `class` 适合某一张表做局部例外。 这三层会按顺序合并,所以你不需要为了改一张表的表头颜色,复制整套预设主题。 ## 先建立一个心智模型 全局 `theme` 最常用的入口是: ```ts createVTableGuild({ theme: { table: { slots: {}, variants: {}, defaultVariants: {}, }, }, }) ``` 可以把它理解成三块: - `slots` 直接改某个主题 slot 的 class,比如 `th`、`td`、`root`、`loading` - `variants` 改条件样式,比如 `hoverable.true.td`、`bordered.true.root` - `defaultVariants` 改默认开关,比如把全局 `size` 默认值从 `large` 改成 `small` 如果你已经在看 [ui Slot 参考](/guide/ui-slots-reference),那一页列出的 slot key,基本都可以直接映射到 `theme.table.slots`。 ## 全局 theme 怎么写 当你希望整个应用里的表格都遵守同一套视觉规则时,优先在插件层覆盖: ```ts import { createApp } from 'vue' import { createVTableGuild } from '@vtable-guild/vtable-guild' const app = createApp(App) app.use( createVTableGuild({ theme: { table: { slots: { root: 'rounded-2xl ring-1 ring-slate-200', th: 'bg-slate-50 text-slate-900', td: 'align-top', }, defaultVariants: { size: 'small', }, }, }, }), ) ``` ### 示例一:统一表头与正文基线 ```ts createVTableGuild({ theme: { table: { slots: { th: 'bg-slate-50 text-slate-900 font-medium', td: 'align-top', }, }, }, }) ``` ### 示例二:统一改 hover 行背景色 ```css :root { --vtg-table-row-hover-bg: #e6f7ff; } ``` 覆盖 CSS 变量是最推荐的方式,hover 高亮由 JS 状态驱动,能正确处理跨行合并单元格。 ### 示例三:统一改默认 size ```ts createVTableGuild({ theme: { table: { defaultVariants: { size: 'small', }, }, }, }) ``` > [!TIP] > 在 TypeScript 项目里,`theme.table.slots`、`variants` 和 `defaultVariants` 都有精确 key 补全;覆盖值可以直接写你自己的 class 字符串。 ## 什么时候该用 CSS 变量 如果你要改的是颜色、字号、行高、padding 这类“token 值”,优先覆盖 CSS 变量,而不是直接重写 class 结构。 比如只想改行 hover 背景: ```css :root { --vtg-table-row-hover-bg: #e6f7ff; } ``` 这类方式更稳定,尤其适合: - 保留现有 slot 结构,只改颜色或尺寸 - 同时兼容多个实例和多个业务页面 - 希望未来跟随预设升级,减少 class 重写成本 具体变量清单见 [Table CSS 变量参考](/guide/theme-tokens)。 ## 单实例覆盖 当你只想调整某一张表时,优先使用 `ui` 和 `class`: ```vue ``` ## utility 前缀与覆盖规则 默认预编译模式下,库内部 utility class 会输出 `vtg-` 前缀。用户传入的 `ui`、`class`、`rowClassName` 等 class 不会被自动加前缀。 如果要覆盖库内部 utility,也应传同前缀: ```vue ``` 直接传 `px-2` 可能会和内部 `vtg-px-*` 同时存在,不保证覆盖内部样式。 `tailwind3` 和 `tailwind4` 模式下,内部 class 保持无前缀,此时可以继续用普通 Tailwind class 覆盖: ```ts app.use(createVTableGuild({ cssMode: 'tailwind3' })) // 或 app.use(createVTableGuild({ cssMode: 'tailwind4' })) ``` ```vue ``` 更多接入细节见 [包导入与样式](/guide/package-consumption)。 ## 怎么选 - 想切换整套视觉基线,用 `themePreset` - 想统一业务线规则,用全局 `theme` - 想改单张表,用 `ui` 和 `class` - 只想改颜色、尺寸、间距等 token,用 CSS 变量 ## 什么时候不该直接用 slot 如果你的目标只是改表头背景、单元格对齐、边框颜色、hover 背景或默认间距,优先走 `theme`、`ui` 或 CSS 变量。只有在内容结构本身要变化时,再使用 Vue slot。 ## 相关页面 - [ui Slot 参考](/guide/ui-slots-reference) - [Table CSS 变量参考](/guide/theme-tokens) - [预设与语言](/guide/presets-and-locales) - [安装与使用](/guide/installation) --- # Table CSS 变量参考 如果你要改的是颜色、字号、间距、空态尺寸、loading 蒙层这类 token 值,优先覆盖 CSS 变量,而不是直接重写 slot class。 ```css :root { --vtg-table-row-hover-bg: #e6f7ff; --vtg-table-header-bg: #f8fafc; } ``` 这种方式适合: - 保留预设和 slot 结构,只改视觉 token - 在多个页面和多个表格实例之间共享同一套视觉规则 - 希望未来升级预设时,减少 class 重写带来的维护成本 ## 推荐优先级 一般按这个顺序选择: 1. 只改颜色、字号、间距等值,用 CSS 变量 2. 需要改 slot 的 class 结构,用全局 `theme` 或实例级 `ui` 3. 需要改内容结构,再用 Vue slot ## 核心视觉变量 | 变量名 | 作用 | | ---------------------------------- | --------------------------------------- | | `--vtg-table-bg` | 表格主体背景,对应 `table`、`td` 等区域 | | `--vtg-table-header-bg` | 表头、标题、页脚、摘要行背景 | | `--vtg-table-header-color` | 表头文字颜色 | | `--vtg-table-text-color` | 正文文字颜色 | | `--vtg-table-border-color` | 表格边框和单元格分隔线 | | `--vtg-table-header-split-color` | antdv 风格表头分割线 | | `--vtg-table-header-sort-hover-bg` | 可排序表头 hover 背景 | | `--vtg-table-header-sort-bg` | 已激活排序的列表头背景 | | `--vtg-table-body-sort-bg` | 已激活排序的列单元格背景 | ## 行状态变量 | 变量名 | 作用 | | -------------------------------------- | ------------------------------------------------------------------- | | `--vtg-table-row-hover-bg` | `hoverable` 行 hover 背景 | | `--vtg-table-row-striped-bg` | `striped` 斑马纹背景,**仅 element-plus 预设生效**(见下) | | `--vtg-table-row-selected-bg` | 选中行背景 | | `--vtg-table-row-selected-hover-bg` | 选中行 hover 背景 | | `--vtg-table-row-drop-indicator-color` | 行拖拽排序的放置指示线颜色(见 [行拖拽排序](/guide/row-drag-sort)) | | `--vtg-table-expanded-row-bg` | 展开行内容背景,当前主题实现里带有默认 fallback | > [!WARNING] > `--vtg-table-row-striped-bg` 只有 element-plus 预设读取。**默认的 antdv 预设把斑马纹背景写死在 > slot class 里**(`rgba(0, 0, 0, 0.02)`,对齐 antdv 原生表现),覆盖这个变量不会有任何效果。 > 在 antdv 预设下要改斑马纹,请覆盖 `td` slot: > > ```vue > > ``` ## 排版与间距变量 | 变量名 | 作用 | | ------------------------------------ | ------------------------------ | | `--vtg-table-font-family` | 表格字体族 | | `--vtg-table-font-size` | 表格字号 | | `--vtg-table-line-height` | 表格行高 | | `--vtg-table-cell-padding-inline-lg` | `size='large'` 的横向 padding | | `--vtg-table-cell-padding-block-lg` | `size='large'` 的纵向 padding | | `--vtg-table-cell-padding-inline-md` | `size='middle'` 的横向 padding | | `--vtg-table-cell-padding-block-md` | `size='middle'` 的纵向 padding | | `--vtg-table-cell-padding-inline-sm` | `size='small'` 的横向 padding | | `--vtg-table-cell-padding-block-sm` | `size='small'` 的纵向 padding | ## 筛选面板变量 | 变量名 | 作用 | | ---------------------------------------- | ---------------------------------------------------------------- | | `--vtg-table-filter-dropdown-max-height` | 筛选面板选项区的最大高度,超出后内部滚动。未声明时回退到 `264px` | antdv 预设不声明这个变量,走 `264px` 回退值;element-plus 预设声明为 `280px`。 ## 空态与加载变量 | 变量名 | 作用 | | --------------------------------------- | -------------------- | | `--vtg-table-loading-overlay-bg` | loading 遮罩层背景 | | `--vtg-table-empty-margin-block` | 空态上下外边距 | | `--vtg-table-empty-image-height` | 空态图形高度 | | `--vtg-table-empty-image-margin-bottom` | 空态图形与文字间距 | | `--vtg-table-empty-image-opacity` | 空态图形透明度 | | `--vtg-table-empty-border-color` | antdv 空态插画边框色 | | `--vtg-table-empty-shadow-color` | antdv 空态插画阴影色 | | `--vtg-table-empty-content-color` | antdv 空态插画填充色 | > [!NOTE] > 空态插画相关变量主要用于当前内置空态视觉,尤其是 antdv 预设。若你只关心空态文案或布局,通常改 `empty`、`emptyWrapper`、`emptyText` 这些 slot 会更直接。 ## 常见场景示例 ### 改表头背景和边框 ```css :root { --vtg-table-header-bg: #f8fafc; --vtg-table-border-color: #e2e8f0; } ``` ### 改 hover 与选中态 ```css :root { --vtg-table-row-hover-bg: #eff6ff; --vtg-table-row-selected-bg: #dbeafe; --vtg-table-row-selected-hover-bg: #bfdbfe; } ``` ### 统一改紧凑型间距 ```css :root { --vtg-table-cell-padding-inline-sm: 10px; --vtg-table-cell-padding-block-sm: 6px; } ``` ## 变量、theme、ui 怎么分工 - 只改 token 值:优先 CSS 变量 - 统一改 slot class 结构:用全局 `theme` - 只改某一张表:用 `ui` ## 相关页面 - [三层主题覆盖](/guide/theme-overrides) - [ui Slot 参考](/guide/ui-slots-reference) - [预设与语言](/guide/presets-and-locales) --- # 标题、页脚与摘要行 这组能力用于在表格上下补充结构化信息。它们的分工可以简单理解为: - `title` 表格上方的信息区 - `footer` 表格下方的补充说明 - `summary` 和当前数据直接相关的汇总行 ## 在线示例 ```vue // @/demos/title-footer-summary/basic.vue ``` ## 基础示例 摘要行组件从 `VTableSummary` 导入,`Row` / `Cell` 挂在它上面。`Cell` 的 `index` 对应列下标。 ```vue ``` ## 什么时候用哪一个 - `title` 标题、统计摘要、筛选说明、批量操作提示 - `footer` 说明文字、更新时间、口径备注 - `summary` 金额合计、平均值、总数和选中项汇总 ## 使用边界 - 只是放一段说明文字时,优先用 `title` 或 `footer` - `summary` 更适合表达和当前数据直接相关的结果,而不是通用描述 - 如果页面外层已经有完整卡片头部,表格 `title` 可以只承载局部状态信息 ## 相关页面 - [多级表头与单元格合并](/guide/grouped-and-merged-cells) - [自定义行与插槽](/guide/api-wiring-and-slots) --- # 树形表格 当你的数据天然带有父子层级时,应该使用树形表格,而不是展开行。树形表格会基于 `childrenColumnName`、缩进宽度和展开状态来管理多级节点的展示方式。 ## 在线示例 三层组织树,受控展开(`expandedRowKeys` + `onExpandedRowsChange`),勾选父节点会联动子节点。 ```vue // @/demos/tree-table/basic.vue ``` ## 基础示例 ```vue ``` ## 常用控制项 - `childrenColumnName` 指定子节点字段名 - `indentSize` 控制层级缩进宽度 - `defaultExpandedRowKeys` 设置默认展开节点 - `expandedRowKeys` 改成完全受控的展开状态 - `rowSelection.checkStrictly` 控制父子选择是否联动 ## 什么时候用 - 数据本身有父子层级,而不是附加详情 - 你需要统一处理节点展开、缩进和父子选择关系 - 页面里既有树结构,又希望保留普通表格的列定义和交互方式 ## 已知限制 - **不支持懒加载**:当前没有提供 `loadData` 等按需加载子节点的能力,所有子节点数据必须预先放在 `dataSource` 中。如果数据量较大,建议在业务层自行拉取完整树结构后再传入。 ## 相关页面 - [行选择](/guide/selection) - [展开行](/guide/expandable-rows) --- # 类型参考 这一页只整理公开 TypeScript 类型:查“该导入哪个类型”和“类型之间是什么关系”。组件行为、默认值和事件语义请看 [API Reference](/guide/api-reference)。 所有类型都推荐从 `@vtable-guild/vtable-guild` 导入。 ```ts import type { TableColumnType, TableColumnsType, RowSelection, Expandable, } from '@vtable-guild/vtable-guild' ``` 如果你正在对齐 ant-design-vue 的列类型命名,优先使用 `TableColumnType` 和 `TableColumnsType`。它们分别等价于 `ColumnType` 和 `ColumnsType`。 ## 表格核心类型 ### Key 行、列和内部状态使用的唯一标识。 ```ts type Key = string | number ``` ### DataIndex 列读取行数据时使用的字段路径。 ```ts type DataIndex = string | number | Array ``` ### AlignType 列内容对齐方式。 ```ts type AlignType = 'left' | 'center' | 'right' ``` ### Breakpoint 响应式列使用的断点类型。当前公开类型名是 `Breakpoint`,没有 `Breakpoints` 复数类型。 ```ts type Breakpoint = 'xxxl' | 'xxl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs' ``` ### SortOrder 排序方向。`null` 表示无排序状态。 ```ts type SortOrder = 'ascend' | 'descend' | null ``` ### ColumnSorter 列排序器类型。业务代码里通常直接写在 `ColumnType['sorter']` 上。 ```ts type SorterFn = (a: TRecord, b: TRecord) => number type ColumnSorter = | boolean | SorterFn | { compare?: SorterFn multiple?: number } ``` ### ColumnFilterItem 列筛选项,支持树形结构。 ```ts interface ColumnFilterItem { text: string value: string | number | boolean children?: ColumnFilterItem[] } ``` ### ColumnType 叶子列配置。它承载数据读取、渲染、排序、筛选、固定列、列宽拖拽和响应式可见性等能力。 ```ts const nameColumn: TableColumnType = { title: 'Name', dataIndex: 'name', key: 'name', sorter: true, } ``` 多数业务场景优先使用 [`TableColumnsType`](#columnstype),因为它同时支持列组和占位常量。 ### ColumnGroupType 列组配置。`children` 内继续放叶子列或列组。 ```ts const grouped: ColumnGroupType = { title: 'Profile', children: [ { title: 'Name', dataIndex: 'name', key: 'name' }, { title: 'Age', dataIndex: 'age', key: 'age' }, ], } ``` ### ColumnsType `columns` prop 的推荐类型。 ```ts type ColumnsType = Array | ColumnGroupType | ColumnSentinel> ``` ```ts const columns: TableColumnsType = [ { title: 'Name', dataIndex: 'name', key: 'name' }, { title: 'Age', dataIndex: 'age', key: 'age', responsive: ['md', 'lg', 'xl'] }, ] ``` ### TableColumnType 和 TableColumnsType 兼容命名别名: ```ts type TableColumnType = ColumnType type TableColumnGroupType = ColumnGroupType type TableColumnsType = ColumnsType ``` ## 渲染与结构类型 ### CellAdditionalProps 用于 `customCell`、`customHeaderCell`、`customRow` 和 `customHeaderRow` 返回额外属性。 ```ts interface CellAdditionalProps { class?: string className?: string style?: CSSProperties colSpan?: number rowSpan?: number /** colSpan / rowSpan 的小写别名,与原生属性写法一致,两种都接受 */ colspan?: number rowspan?: number onClick?: (event: MouseEvent) => void onMouseenter?: (event: MouseEvent) => void onMouseleave?: (event: MouseEvent) => void [key: string]: unknown } ``` 索引签名允许挂任意额外属性(`data-*`、`aria-*` 等),它们会直接落到对应的 DOM 元素上。 ### RenderedCell `customRender` 或选择列 `renderCell` 可返回的对象形态。 ```ts interface RenderedCell { props?: CellAdditionalProps children?: VNodeChild } ``` ### CustomRenderContext `column.customRender` 的参数类型。 ```ts interface CustomRenderContext { text: unknown value: unknown record: TRecord index: number renderIndex: number column: ColumnType } ``` ## 交互类型 ### RowSelection `rowSelection` prop 的类型,用于多选、单选、受控选择和选择列渲染。 ```ts const rowSelection: RowSelection = { selectedRowKeys, onChange: (keys, rows) => { selectedRowKeys = keys }, } ``` ### RowSelectionType ```ts type RowSelectionType = 'checkbox' | 'radio' ``` ### SelectionItem 自定义批量选择菜单项。 ```ts interface SelectionItem { key: string text: string | VNodeChild onSelect?: (changeableRowKeys: Key[]) => void } ``` ### Expandable `expandable` prop 的类型,用于展开行。 ```ts const expandable: Expandable = { expandedRowRender: (record) => record.description, } ``` ### TableFiltersInfo `change` 事件里的 filters 参数。 ```ts type TableFiltersInfo = Record ``` ### VTableSorterResult `change` 事件里的 sorter 参数。 ```ts type VTableSorterResult = SorterResultLike | Array> ``` ### TableChangeExtra `change` 事件里的 extra 参数。 ```ts interface TableChangeExtra { action: 'sort' | 'filter' | 'select' currentDataSource: TRecord[] } ``` ### RowDragSortInfo `rowDragEnd` 事件的 info 参数,见[行拖拽排序](/guide/row-drag-sort)。 ```ts interface RowDragSortInfo { /** 拖拽行的 key */ draggedKey: Key /** 放置目标行的 key */ targetKey: Key /** 拖拽完成后的全量行 key 顺序(对应事件的 newData;树形数据按数据顺序递归包含子节点) */ orderedKeys: Key[] } ``` ## Slot 类型 ### TableBodyCellSlotProps `bodyCell` slot 参数。 ```ts interface TableBodyCellSlotProps { text: unknown record: TRecord index: number column: ColumnType } ``` ### TableHeaderCellSlotProps `headerCell` slot 参数。 ```ts interface TableHeaderCellSlotProps { title: VNodeChild | undefined column: ColumnType | ColumnGroupType index: number } ``` ### CustomFilterDropdownSlotProps `customFilterDropdown` slot 参数。 ```ts interface CustomFilterDropdownSlotProps { column: ColumnType selectedKeys: (string | number | boolean)[] setSelectedKeys: (keys: (string | number | boolean)[]) => void confirm: (options?: { closeDropdown?: boolean }) => void clearFilters: (options?: { confirm?: boolean; closeDropdown?: boolean }) => void filters: ColumnFilterItem[] visible: boolean close: () => void } ``` ### TableDataSlotProps `title` 和 `footer` slot 参数。 ```ts interface TableDataSlotProps { data: TRecord[] } ``` ### TableSlotsDecl `VTable` 的 slot 声明类型,适合需要包装表格组件时使用。 ```ts interface TableSlotsDecl { bodyCell?: (props: TableBodyCellSlotProps) => VNodeChild headerCell?: (props: TableHeaderCellSlotProps) => VNodeChild empty?: () => VNodeChild loading?: () => VNodeChild customFilterDropdown?: (props: CustomFilterDropdownSlotProps) => VNodeChild customFilterIcon?: (props: { column: ColumnType; filtered: boolean }) => VNodeChild title?: (props: TableDataSlotProps) => VNodeChild footer?: (props: TableDataSlotProps) => VNodeChild summary?: () => VNodeChild } ``` ## 常量类型 ### SelectionSentinel `rowSelection.selections` 可用的默认批量选择常量类型。 ```ts import { SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE } from '@vtable-guild/vtable-guild' ``` ### ColumnSentinel `columns` 顶层可用的列占位常量类型。 ```ts import { EXPAND_COLUMN, SELECTION_COLUMN } from '@vtable-guild/vtable-guild' const columns: TableColumnsType = [ { title: 'Name', dataIndex: 'name', key: 'name' }, EXPAND_COLUMN, SELECTION_COLUMN, ] ``` `ExpandColumnSentinel` 对应 `EXPAND_COLUMN`,`SelectionColumnSentinel` 对应 `SELECTION_COLUMN`。 ## 组件与事件类型 ### TableProps `VTable` props 的完整类型。封装二次组件时优先使用这个类型。 ```ts type MyTableProps = TableProps ``` ### VTableEventProps `change`、`resizeColumn` 与 `rowDragEnd` 事件 props 类型。 ```ts interface VTableEventProps { onChange?: (filters, sorter, extra) => void onResizeColumn?: (column: ColumnType, width: number) => void onRowDragEnd?: (newData: TRecord[], info: RowDragSortInfo) => void } ``` ### VTablePublicProps `TableProps` 与 `VTableEventProps` 的组合类型。 ### VTableComponent 泛型化后的 `VTable` 组件类型。 ### SummaryFixed `VTableSummary` 的 fixed 类型。 ```ts type SummaryFixed = boolean | 'top' | 'bottom' ``` ## 主题与插件类型 ### ThemePresetName 内置主题预设名。 ```ts type ThemePresetName = 'antdv' | 'element-plus' ``` ### VTableGuildOptions `createVTableGuild()` 的配置类型。 ```ts interface VTableGuildOptions { themePreset?: ThemePresetName cssMode?: VTableGuildCssMode classPrefix?: string theme?: VTableGuildThemeOverrides locale?: LocaleName locales?: LocaleRegistry localeOverrides?: DeepPartial /** 兼容类名开关,默认关闭。安装时读取一次,不支持运行时切换 */ compatClass?: boolean } ``` `cssMode` 与 `classPrefix` 的取值和使用场景见 [安装与使用](/guide/installation), `compatClass` 见 [从 ant-design-vue 迁移](/guide/migration-from-antd#保留旧的覆盖-css-兼容类名)。 ### VTableGuildCssMode 样式模式,需要与实际引入的 CSS 入口一致。 ```ts type VTableGuildCssMode = 'prebuilt' | 'tailwind3' | 'tailwind4' ``` ### LocaleName 语言标识类型。内置语言目前由 preset 提供,业务也可以注册自己的语言标识。 ```ts type LocaleName = string ``` ### LocaleRegistry 语言包注册表。 ```ts type LocaleRegistry = Record ``` ### ThemeOverrideConfig 主题覆盖类型,用于保留 slot、variant 和 default variant 的补全。 ```ts import type { TableThemeConfig, ThemeOverrideConfig } from '@vtable-guild/vtable-guild' const tableTheme: ThemeOverrideConfig = { slots: { th: 'font-semibold', }, } ``` ### TableSlots 和 TableThemeConfig Table 主题 slot 名和主题配置类型。完整 slot 行为见 [ui Slot 参考](/guide/ui-slots-reference)。 ```ts import type { TableSlots, TableThemeConfig } from '@vtable-guild/vtable-guild' ``` 同类主题类型还包括 `ButtonThemeConfig`、`CheckboxThemeConfig`、`RadioThemeConfig`、`InputThemeConfig`、`TooltipThemeConfig` 和 `ScrollbarThemeConfig`。 ## 相关页面 - [API Reference](/guide/api-reference) - [ui Slot 参考](/guide/ui-slots-reference) - [三层主题覆盖](/guide/theme-overrides) --- # ui Slot 参考 `VTable` 的 `ui` prop 是实例级别的样式覆盖入口。每个 key 对应一个 **theme slot**,值为 Tailwind CSS class 字符串,会与预设默认 class 通过 `cn()` 智能合并。 ```vue ``` > [!TIP] > 安装并导入 `@vtable-guild/vtable-guild` 后,在 TypeScript 项目中 `ui` prop 的所有 slot key 都有自动补全。 --- ## 这页不只给 `ui` 用 这页列出的 slot 和 variant,不只是 `ui` prop 的参考表,也对应全局 `theme` 的写法: - `ui.th` 对应 `theme.table.slots.th` - `ui.td` 对应 `theme.table.slots.td` - `hoverable.true.td` 对应 `theme.table.variants.hoverable.true.td` - `size: 'small'` 对应 `theme.table.defaultVariants.size = 'small'` 也就是说,这页可以当成“Table 主题系统可覆盖项总表”来看。 ## 从 slot 表映射到全局 theme ```ts createVTableGuild({ theme: { table: { slots: { th: 'bg-slate-50 text-slate-900', td: 'align-top', }, variants: { hoverable: { true: { td: 'group-hover/row:bg-blue-50', }, }, }, defaultVariants: { size: 'small', }, }, }, }) ``` 如果你要的是应用级统一规范,优先看 [三层主题覆盖](/guide/theme-overrides)。如果你只是改单张表,再回到 `ui`。 ## 快速示例:修改行 hover 背景色 行 hover 效果由 `hoverable` variant 控制,hover 高亮通过 JS 状态驱动,能正确处理跨行合并单元格。自定义 hover 背景色推荐覆盖 CSS 变量: ### 方式一:覆盖 CSS 变量(推荐) ```css :root { --vtg-table-row-hover-bg: #e6f7ff; } ``` ### 方式二:通过 `ui` prop 覆盖 `tdRowHover` slot ```vue ``` ### 方式三:通过全局 `theme` ```ts app.use( createVTableGuild({ theme: { table: { slots: { tdRowHover: 'bg-blue-50', }, }, }, }), ) ``` --- ## 完整 Slot 列表 以下按功能分组列出所有可用的 theme slot key。它们既可用于 `ui`,也可用于全局 `theme.table.slots`。 ### 核心结构 | Slot | 说明 | | ------------------- | --------------------------------------------------------------------------------- | | `root` | 表格最外层容器。控制字体、字号、行高。 | | `wrapper` | `` 元素的滚动包裹层。 | | `rootAutoHeight` | `scroll.y: 'auto'` 时叠加在 `root` 上的自动高度布局(填满父容器)。 | | `wrapperAutoHeight` | `scroll.y: 'auto'` 时叠加在 `wrapper` 上的自动高度布局(吃剩余高度)。 | | `table` | `
` 元素。控制背景色、文字色、边框间距。 | | `thead` | `` 元素。 | | `tbody` | `` 元素。 | | `tr` | `` 元素。默认带 `group/row`,供子元素做 hover 匹配。 | | `th` | 表头单元格 `
`。控制背景、文字色、边框和分割线。 | | `td` | 数据单元格 ``。控制背景、文字色、边框;hover、选中、斑马纹通过 variant 追加。 | ### 表头与单元格包装 | Slot | 说明 | | ------------------ | ------------------------------- | | `headerCellInner` | 表头单元格内部的 flex 包裹层。 | | `bodyCellEllipsis` | `ellipsis` 列内容的文本截断层。 | ### 分组表头 | Slot | 说明 | | -------------------- | ---------------------------- | | `groupedHeaderTable` | 多级表头中的内层 ``。 | | `groupedHeaderTh` | 分组表头 ``。 | | `trDropAbove` | 放置目标行(插入到其上方)的 `` 指示线。 | | `trDropBelow` | 放置目标行(插入到其下方)的 `` 指示线。 | ### 行选择下拉 | Slot | 说明 | | ----------------------- | ---------------------------- | | `selectionDropdown` | 行选择下拉面板。 | | `selectionDropdownItem` | 行选择下拉项。 | | `selectionExtra` | 行选择列头部的额外触发图标。 | ### 标题、页脚与摘要 | Slot | 说明 | | ------------- | -------------- | | `title` | 表格标题区域。 | | `footer` | 表格页脚区域。 | | `summary` | 摘要容器。 | | `summaryRow` | 摘要 ``。 | | `summaryCell` | 摘要 ``。 | | `expandedRowCell` | 展开内容 `
`。 | | `groupedHeaderTd` | 分组表头 ``。 | ### 排序 | Slot | 说明 | | ----------------- | -------------------------------- | | `thSortable` | 可排序列的 `` 附加样式。 | | `thSorted` | 已激活排序的列 `` 背景。 | | `tdSorted` | 已激活排序的列 `` 背景。 | | `sortButton` | 排序图标容器。 | | `sortIconDown` | 降序图标的间距调整。 | | `sortAreaOuter` | 排序区最外层 flex 包裹。 | | `sortAreaWrapper` | 标题和排序图标之间的 flex 包裹。 | | `sortAreaTitle` | 排序标题文本容器。 | ### 筛选图标 | Slot | 说明 | | ------------------- | ------------------ | | `filterIconWrapper` | 筛选图标包裹容器。 | | `filterIcon` | 筛选触发图标本身。 | ### 筛选下拉面板 | Slot | 说明 | | ---------------------------------- | --------------------------------------------------- | | `filterDropdown` | 筛选面板根容器。 | | `filterDropdownList` | 筛选选项列表容器。 | | `filterDropdownItem` | 单个筛选项。 | | `filterDropdownItemSelected` | 选中项样式。 | | `filterDropdownItemSelectedSingle` | 单选(`filterMultiple: false`)下的选中项附加样式。 | | `filterDropdownItemHover` | hover 项样式。 | | `filterDropdownContentWrapper` | 选项内容包裹层。 | | `filterDropdownActions` | 底部操作栏。 | | `filterDropdownResetButton` | 底部「重置」按钮的附加样式。 | | `filterDropdownConfirmButton` | 底部「确定」按钮的附加样式。 | | `filterDropdownSearch` | 搜索区外层。 | | `filterDropdownSearchField` | 搜索输入框容器。 | | `filterDropdownSearchIcon` | 搜索图标。 | | `filterDropdownSearchInput` | 搜索输入框。 | | `filterDropdownListEmpty` | 空结果提示。 | ### 筛选树形结构 | Slot | 说明 | | ---------------------------------- | --------------------- | | `filterDropdownSwitcher` | 树节点展开/折叠按钮。 | | `filterDropdownSwitcherExpanded` | 展开状态。 | | `filterDropdownSwitcherCollapsed` | 折叠状态。 | | `filterDropdownSwitcherNoop` | 不可切换节点占位。 | | `filterDropdownTreeWrapper` | 树列表包裹层。 | | `filterDropdownTreeList` | 树列表 `
    `。 | | `filterDropdownTreeItem` | 单个树节点行。 | | `filterDropdownTreeContentWrapper` | 树节点内容包裹层。 | | `filterDropdownTreeItemSelected` | 选中节点样式。 | | `filterDropdownTreeItemMatched` | 搜索命中节点样式。 | | `filterDropdownTreeCheckAll` | “全选” 行。 | ### 空状态 | Slot | 说明 | | -------------- | ------------------ | | `empty` | 空状态根容器。 | | `emptyWrapper` | 空状态内容包裹层。 | | `emptyIcon` | 空状态图标区域。 | | `emptyText` | 空状态文字。 | ### 加载态 | Slot | 说明 | | ---------------- | ----------------------------- | | `loading` | 覆盖整张表的 loading 遮罩层。 | | `loadingSpinner` | loading 图标。 | ### 行选中 | Slot | 说明 | | -------------------- | ------------------------------------ | | `tdSelected` | 选中行的 `
` 背景。 | | `tdRowHover` | hover 时普通行的 `` 背景。 | | `tdRowSelectedHover` | hover 时选中行的 `` 背景叠加层。 | ### 行拖拽排序 | Slot | 说明 | | ------------- | -------------------------------------------- | | `trDragging` | 拖拽中的行 `
`。 | ### 固定列与固定表头 | Slot | 说明 | | ------------------------ | -------------------------------- | | `headerWrapper` | 固定表头模式下的表头滚动包裹层。 | | `bodyWrapper` | 固定表头模式下的表体滚动包裹层。 | | `fixedCell` | 固定列单元格。 | | `fixedDividerLeft` | 左固定列分隔线。 | | `fixedDividerRight` | 右固定列分隔线。 | | `fixedShadowLeft` | 左固定列阴影层。 | | `fixedShadowRight` | 右固定列阴影层。 | | `fixedShadowLeftHidden` | 左侧阴影隐藏状态。 | | `fixedShadowRightHidden` | 右侧阴影隐藏状态。 | ### 展开行 | Slot | 说明 | | --------------------------- | ------------------------ | | `expandIcon` | 展开按钮基础样式。 | | `expandIconExpanded` | 展开状态。 | | `expandIconCollapsed` | 折叠状态。 | | `expandIconSpaced` | 不可展开行的占位符。 | | `expandIconDisabled` | 禁用状态。 | | `expandIconSymbol` | 展开图标的 symbol 容器。 | | `expandIconSymbolExpanded` | 展开 symbol 状态。 | | `expandIconSymbolCollapsed` | 折叠 symbol 状态。 | | `expandedRow` | 展开行 `
`。 | ### 树形展开 | Slot | 说明 | | ------------------------------- | ---------------------- | | `treeExpandIcon` | 树形展开按钮基础样式。 | | `treeExpandIconExpanded` | 展开状态。 | | `treeExpandIconCollapsed` | 折叠状态。 | | `treeExpandIconSpaced` | 叶子节点占位。 | | `treeExpandIconDisabled` | 禁用状态。 | | `treeExpandIconSymbol` | 树形 symbol 容器。 | | `treeExpandIconSymbolExpanded` | 树形展开 symbol 状态。 | | `treeExpandIconSymbolCollapsed` | 树形折叠 symbol 状态。 | ### 列宽拖拽 | Slot | 说明 | | -------------- | -------------- | | `resizeHandle` | 列宽拖拽手柄。 | --- ## Variant 列表 除了直接的 slot 覆盖,主题还通过 variant 控制条件样式。它们可以通过 props 控制,也可以通过全局 `theme.table.variants` 和 `theme.table.defaultVariants` 调整。 | Variant | 值 | 默认值 | 影响的 Slot | | ----------- | ---------------------------- | ------- | ------------------------------------------------------------- | | `size` | `small` / `middle` / `large` | `large` | `th`、`td`、`title`、`footer`、`summaryCell` 的 padding | | `bordered` | `true` / `false` | `false` | `root`、`th`、`td`、`tbody`、`title`、`footer`、`summaryCell` | | `striped` | `true` / `false` | `false` | `td`,偶数行背景 | | `hoverable` | `true` / `false` | `true` | `td`,行 hover 背景 | | `loading` | `true` / `false` | 无 | `table`,半透明和禁交互状态 | ## 进一步阅读 - [三层主题覆盖](/guide/theme-overrides) - [Table CSS 变量参考](/guide/theme-tokens) - [预设与语言](/guide/presets-and-locales) - [API Reference](/guide/api-reference) --- # 虚拟滚动 虚拟滚动是 vtable-guild 最值得优先关注的增强能力之一。对于长列表页面,它的价值不是“多一个开关”,而是让你不必再维护另一套大数据量表格方案。 ## 在线示例:10 万行 下面这张表默认装载 **10 万行**真实数据(页面内运行时生成,不是分页假象)。滚动它,同时留意 DOM 里始终只有可视区的十几行。左侧两列仍然固定,「评分」列仍然可以排序。 ```vue // @/demos/virtualization/large.vue ``` ## 怎么开启 虚拟滚动需要同时满足两个条件: - `virtual` 为 `true` - `scroll.y` 提供一个有效高度 ```vue ``` ## 关键边界 - 只写 `virtual`,不写 `scroll.y`,不会真正启用虚拟滚动 - `rowKey` 需要保持稳定,否则滚动窗口复用时容易出现状态错位 - 虚拟滚动提升的是渲染性能,不会替代服务端分页、慢查询优化或大对象计算优化 ## 定高快路径 `rowHeight` 默认路径支持**不定行高**:每行挂载后实测高度,再据此算可视区。代价是挂载和滚动都要维护一张位置表。 如果你的每一行高度确实相同,可以显式声明 `rowHeight`,跳过全部行高测量——可视区计算恒为 O(1), 挂载与滚动开销不再随总行数增长。 ```vue ``` - 仅在 `virtual` 下生效,单位 px - **前提是每行实际高度确实等于该值**。存在换行文本、`ellipsis: false` 的长内容或自定义高度渲染时, 不要传这个 prop,交给默认的实测路径 - 我们刻意不做自动探测:从 `size` 预设猜行高在长文本换行时会静默算错,而错误表现为行错位或空隙, 很难归因,所以要求你主动声明 - dev 构建会实测首行高度,与声明值相差超过 1px 时在控制台告警;生产构建跳过这次测量 ## 自动高度 `scroll.y: 'auto'` `scroll.y` 传数字表示**固定的**表体视口高度;传 `'auto'` 则表示**自动适应内容区**: 表格充满父容器,表体高度 = 父容器可用高度 − 表头 − 固定 summary,由组件内部测量扣减。 你不必再自己监听 resize、也不必去读表头高度来手工扣减——浏览器 Ctrl+滚轮缩放、 窗口拖拽、父布局变化都会自动跟随。下方演示可在「块级父」与「flex 布局 + 兄弟节点」 两种父容器形态之间切换。 ```vue // @/demos/virtualization/auto-height.vue ``` ### 父容器要求 `'auto'` 依赖一条**确定的高度链**: - 普通块级父容器:父容器需要有确定高度(如 `height: 400px`),且 VTable 是它的专用填充子项 - flex 布局:允许存在兄弟节点,但高度链必须确定,且 VTable 的可收缩祖先需要 `min-height: 0`—— 否则高度链在那里断掉,测不到可用高度 - 内容自然撑高的父容器(高度不确定)不适用;dev 构建下连续测不到可用高度会在控制台提示 flex 布局 + 兄弟节点的写法:把上方演示切到「flex 布局 + 兄弟节点」后,取消勾选 `min-height: 0` 并拖动高度滑杆,可以现场复现高度链断裂——flex 子项默认 `min-height: auto` 会拒绝收缩,容器缩了表格却不跟随:表体被裁切、底部摘要栏被挤出可视区。 ### 行为细节 - 少量数据按内容自然收缩(maxHeight 语义),超出可用区域后才出现纵向滚动 - 普通模式与虚拟模式都支持;虚拟模式下即使 `showHeader: false` 也保持可滚动的表体 - 数字 `scroll.y` 行为完全不变;非虚拟模式下其他 CSS 字符串(`'100%'`、`calc(...)`)仍原样生效 - **虚拟模式下的字符串约束**:仅兼容正数 px(如 `'480px'`,dev 会提示改用数字); `'100%'`、`'50vh'`、`calc(...)`、负数等无法可靠解析的值会告警并回落 400px 视口—— 保持虚拟可用,而不是回落全量渲染的普通表体(万行宽表上那是秒级冻结) ## 横向虚拟化 `virtualColumn` 上面那个开关虚拟化的是**行**。列很多时(百列量级)瓶颈会换一个地方:每个可见单元格 都是一个组件实例,12 行 × 200 列就是 2,400 个,滚动时每帧都要重新走一遍。 `virtualColumn` 把可见单元格数从「行 × 总列数」降到「行 × 可视列数」。 ```vue ``` 实测 1 万行 × 200 列:可视列数 200 → 13,连续滚动 longtask 4,391ms → **0**, 排序切换 126ms → 75ms,DOM 节点数 3,659 → 1,415。完整数字与方法见[性能文档](https://github.com/parade0393/vtable-guild/blob/master/docs/performance.md)。 **默认关闭,而且应该保持关闭**,除非你的列数真的很多:6 列时它既无收益也无代价 (实测完全持平),但会多一次表头测量。 ### 在线示例:1 万行 × 200 列 下面这张表 200 个叶子列,两端各有固定列。左右滚动时留意「渲染列数」——开关一关, 它立刻从十几跳回 200,而这 200 个单元格每行都要重建一次。`C1` 列仍然可以排序。 ```vue // @/demos/virtualization/wide-columns.vue ``` ### 什么时候它会被忽略 不满足下列任一前提时,`virtualColumn` 会被忽略、表体回落到渲染全部列, dev 构建会在控制台给出原因: - 没有开启 `virtual` - 列上有 `customCell` / `customRender`——它们可能返回 `colSpan` / `rowSpan`, 单元格合并会让某个 `` 缺席,进而破坏列宽对齐(虚拟模式本就不支持合并) - 固定列没有分列两端:左固定必须连成前缀、右固定必须连成后缀 - `showHeader: false` 且存在非数字列宽——此时没有表头可供实测,也算不出来 ### 已知边界 - 列宽不要求你声明数字:`auto`、百分比都支持,因为宽度是从表头**量**出来的 - 首帧会先渲染全部列,量到宽度后才收窄。所以它优化的是**滚动与更新**, 首次渲染耗时基本不变 - 列滚出窗口时,挂在该列表头上的筛选面板 / tooltip 会随之卸载 - 表头本身不虚拟化:列数极多时仍会渲染全部表头单元格(一次性成本,非每行) ## 什么时候用 - 列表行数很多,滚动明显卡顿 - 你希望在同一张表里保留列定义、主题和交互能力,而不是切换到另一种列表组件 - 当前页面的主要瓶颈来自 DOM 数量,而不是接口本身 ## 自己量一遍 不必相信这里的任何说法——[性能对照页](/perf/)可以在你自己的机器上,把 vtable-guild、 ant-design-vue Table、antdv-next、el-table-v2 与 vxe-table 放在**同一批数据、同一套列配置** 下跑一遍(1k / 1 万 / 10 万行 × 6 / 50 / 200 列),给出渲染耗时、DOM 节点数与内存, 并一键导出结果。采集方法与已知的不对等之处都写在页面上。 ## 相关页面 - [固定列](/guide/fixed-columns) - [功能对比总览](/comparison/) --- # 为什么选择 vtable-guild vtable-guild 不是一套全新的 UI 体系,而是给已经在使用 ant-design-vue 或 element-plus 的项目提供一条更顺手的表格替换路径。 它的目标很明确:保留你熟悉的列定义、排序筛选和业务集成方式,同时补上原表格在大数据量、列布局控制和主题扩展上的短板。 ## 目标用户 这套库更适合以下场景: - 你的项目已经使用 ant-design-vue 或 element-plus,希望表格视觉与整体 UI 体系保持一致 - 你不想继续为虚拟滚动、列宽拖拽、条纹行和 hover 状态维护额外封装 - 你需要一套能在全局、业务线和单实例三层同时控制样式的主题机制 - 你希望迁移成本可控,而不是把现有表格页面全部推倒重写 ## 它解决的核心问题 ### 1. 原表格能力不够用 业务表格变复杂之后,痛点往往不是“能不能渲染表格”,而是: - 大数据量下滚动和渲染体验差 - 列宽需要用户现场调整,但原表格和业务封装之间还要再补一层约定 - 条纹行、hover 行、边框和空态样式主要靠额外 CSS 覆盖 - 同一套业务代码要接入不同视觉体系时,样式调整成本高 ### 2. 继续在原表格上堆补丁会越来越重 现有业务里最贵的部分通常不是模板语法本身,而是列配置、数据处理、事件联动和页面约定。vtable-guild 的价值在于尽量保留这些使用方式,把增强能力做进表格内部,而不是继续把复杂度压给业务层。 ## 什么时候适合优先考虑它 - 你来自 ant-design-vue,希望在不改掉整套表格心智的前提下补齐虚拟滚动和主题系统 - 你来自 element-plus,希望用统一的 columns + props 模型替代表格能力分散的接入方式 - 你已经开始为同一类表格重复写 CSS hack、滚动补丁或主题封装 ## 什么时候不适合 如果你的页面只是一个非常简单的数据展示表,没有性能、列布局、主题切换或复杂交互需求,继续使用现有 UI 库自带表格通常更省事。 vtable-guild 更适合中大型业务表格,而不是为了“替换而替换”。 --- # 增强与独有能力 这一页只聚焦“相对原表格方案额外得到什么”,不重复完整教程。需要具体使用方式时,请跳到对应指南页。 ## 更顺手的 API ### 尺寸命名与 ant-design-vue 一致 表格尺寸沿用 `small`、`middle`、`large`,和 ant-design-vue 完全相同——从 antdv 迁过来时这一项不用改。默认值是 `large`。 ### TypeScript 使用链路更完整 VTable 提供明确的列类型、行数据类型、事件参数类型,以及主题 key 和 slot key 的类型边界,适合在业务代码里长期维护。 ### 样式覆盖路径更清晰 除了 Vue slot,本库把样式覆盖拆成三层: - `themePreset` 切换整体视觉基线 - 全局 `theme` 统一应用级规则 - 实例级 `ui` 处理单表例外 对应说明见 [三层主题覆盖](/guide/theme-overrides)。 ## 更直接的表格能力 ### 虚拟滚动 通过 `virtual` 配合 `scroll.y` 直接启用,适合长列表和性能敏感页面。详见 [虚拟滚动](/guide/virtualization)。 ### 列设置:列显示与列顺序 `column.visible` 控制列是否显示、`columnOrder` 按列 key 重排顶层列,都是受控属性——显示状态可以持久化成用户偏好。antdv / element-plus 的原生表格都需要自行拼装这类「列设置」面板。详见 [列显示与列顺序](/guide/column-display)。 ### 行拖拽排序 `rowDraggable` 开启原生 HTML5 整行拖拽,拖放结束通过 `rowDragEnd` 返回重排后的数据(受控模式),不需要再引入第三方拖拽库。详见 [行拖拽排序](/guide/row-drag-sort)。 ### 更直接的视觉状态开关 - `striped` 条纹行 - `hoverable` 行 hover 高亮 - `bordered` 边框模式 这些状态都可以直接通过 props 或主题配置开启,不需要再拆散到业务 CSS 里。 ### 多预设支持 当前内置 `antdv` 和 `element-plus` 两套预设,可让同一套表格逻辑接入不同 Vue UI 体系。详见 [预设与语言](/guide/presets-and-locales)。 ## 继续阅读 - [功能对比总览](/comparison/) - [虚拟滚动](/guide/virtualization) - [列宽拖拽](/guide/column-resize) - [列显示与列顺序](/guide/column-display) - [行拖拽排序](/guide/row-drag-sort) - [三层主题覆盖](/guide/theme-overrides) --- # 功能对比总览 这一页只回答一个问题:如果你已经在使用 ant-design-vue Table 或 element-plus Table,vtable-guild 多了什么,迁移成本主要落在哪里。 ## 功能矩阵 | 能力 | ant-design-vue | element-plus | vtable-guild | | -------------------- | ---------------------------------------- | ---------------------------------- | -------------------------------------------------- | | 常见列配置与交互写法 | 支持 | 主要依赖 `el-table-column` | 支持,设计更贴近 ant-design-vue | | 虚拟滚动 | 不支持 | 有独立 Virtualized Table 方案 | 原生支持,直接配合 `virtual` 和 `scroll.y` 使用 | | 滚动体验优化 | 默认滚动体验 | 体验更好,可作参考 | 在 antdv 预设下做了额外打磨,方向参考 element-plus | | 列宽拖拽 | 支持 `resizable`、`minWidth`、`maxWidth` | 支持,通常在 border 模式里使用 | 支持,并沿用接近 antdv 的字段心智 | | 条纹行 | 主要靠 `rowClassName` | 直接使用 `stripe` | 直接使用 `striped` | | hover 开关 | 没有独立开关 | 没有独立开关 | 直接使用 `hoverable` | | 边框模式 | 支持 | 支持 | 支持,直接使用 `bordered` | | 主题预设切换 | 不支持 | 不支持 | 支持 `antdv` / `element-plus` | | slot 级样式覆盖 | 主要依赖 CSS 覆盖 | 主要依赖 class、style 和 slot 组合 | 通过 `ui` 和全局 `theme` 精确覆盖 | | 尺寸命名 | `small / middle / large` | `large / default / small` | `small / middle / large`,与 antdv 一致 | | 内置 locale 预设 | 依赖组件库全局配置 | 依赖组件库全局配置 | 内置 locale 并支持局部覆盖 | ## 结论 - 如果你只需要一张基础表格,原生表格通常已经够用 - 如果你来自 ant-design-vue,vtable-guild 的主要价值是把虚拟滚动、主题系统和更直接的视觉状态开关收进同一套表格模型 - 如果你来自 element-plus,vtable-guild 的主要价值是把表格能力统一到同一套 columns + props 模型里,而不是在普通表格和独立增强方案之间切换 ## 继续阅读 - [增强与独有能力](/comparison/enhancements) - [为什么选择 vtable-guild](/guide/why) - [从 ant-design-vue 迁移](/guide/migration-from-antd) --- # API Reference This page is the behavioral reference: props, events, slots, defaults and controlled/uncontrolled rules. For the full relationships of TypeScript types such as `TableColumnsType`, `Breakpoint` and `RowSelection`, see the [type reference](/guide/type-reference) (Chinese). This page only mentions type names without re-expanding their definitions. ## Import entry Import components, constants and types from `@vtable-guild/vtable-guild`: ```ts import { VTable, VTableSummary, EXPAND_COLUMN, SELECTION_COLUMN, type TableColumnsType, type RowSelection, type Expandable, } from '@vtable-guild/vtable-guild' ``` ## VTable Props ### Data and structure | Prop | Type | Default | Description | | -------------------- | ---------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------- | | `dataSource` | `TRecord[]` | `[]` | Table data source. | | `columns` | [`TableColumnsType`](/guide/type-reference#columnstype) | `[]` | Column configuration: leaf columns, column groups and sentinel constants. | | `columnOrder` | [`Key[]`](/guide/type-reference#key) | - | Column display order. See [column display](/guide/column-display) (Chinese). | | `rowKey` | `string \| (record) => Key` | - | Unique row identity; passing it explicitly is recommended. | | `childrenColumnName` | `string` | `'children'` | Child field name for tree data. | | `indentSize` | `number` | `15` | Tree data indent width in px. | ### Visuals and layout | Prop | Type | Default | Description | | ---------------- | -------------------------------- | --------- | ---------------------------------------------------------------------- | | `size` | `'small' \| 'middle' \| 'large'` | `'large'` | Table size, aligned with ant-design-vue naming. | | `loading` | `boolean \| object` | `false` | Loading state; the object form accepts `spinning`, `indicator`, `tip`. | | `bordered` | `boolean` | `false` | Show borders. | | `striped` | `boolean` | `false` | Zebra striping. | | `hoverable` | `boolean` | `true` | Row hover highlight. | | `tableLayout` | `'auto' \| 'fixed'` | - | Table layout mode. | | `showHeader` | `boolean` | `true` | Whether to show the header. | | `headerEllipsis` | `boolean` | `false` | Also ellipsize headers of columns with `column.ellipsis`. | | `class` | `string` | - | Extra class on the root node. | ### Scrolling and positioning | Prop | Type | Default | Description | | ------------------- | ------------------------------------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `scroll` | `{ x?: number \| string; y?: number \| string }` | - | Horizontal and vertical scroll config; providing `y` creates a fixed-header scroll area. A numeric `y` sets a fixed viewport; `y: 'auto'` fills a parent with a definite height and deducts the header and external summary. In `virtual` mode, other strings must be positive pixel values; relative units fall back to 400px with a development warning. | | `sticky` | `boolean \| TableSticky` | `false` | Sticky header, summary or horizontal scrollbar config. | | `virtual` | `boolean` | `false` | Enable virtual scrolling; requires `scroll.y`. | | `virtualColumn` | `boolean` | `false` | Horizontal virtualization: render only columns in the viewport; requires `virtual`. Pays off with many columns, see [virtualization](/guide/virtualization) (Chinese). | | `rowHeight` | `number` | - | Fixed row height (px), only in `virtual` mode. Declaring it skips all row measurement and makes viewport math O(1) — only pass it if every row truly has that height. | | `getPopupContainer` | `(triggerNode) => HTMLElement` | - | Mount container for filter and selection menus. | ### Theming and locale | Prop | Type | Default | Description | | ----------------- | -------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------- | | `ui` | `SlotProps` | - | Theme slot class overrides for this table instance. See the [ui slot reference](/guide/ui-slots-reference) (Chinese). | | `locale` | [`LocaleName`](/guide/type-reference#localename) | global config or `'zh-CN'` | Locale identifier for this table instance. | | `locales` | [`LocaleRegistry`](/guide/type-reference#localeregistry) | `{}` | Extra locale packs registered on this instance. | | `localeOverrides` | `DeepPartial` | `{}` | Partial locale overrides for this instance. | ### Interactive capabilities | Prop | Type | Default | Description | | ------------------------ | ------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------- | | `rowSelection` | [`RowSelection`](/guide/type-reference#rowselection) | - | Enable the selection column. | | `expandable` | [`Expandable`](/guide/type-reference#expandable) | - | Enable expandable rows. | | `rowDraggable` | `boolean` | `false` | Enable row drag sorting, see [row drag sort](/guide/row-drag-sort) (Chinese). | | `expandedRowKeys` | `Key[]` | - | Controlled expanded keys for tree data. | | `defaultExpandedRowKeys` | `Key[]` | - | Default expanded keys for tree data. | | `defaultExpandAllRows` | `boolean` | `false` | Expand all tree nodes by default. | | `onExpand` | `(expanded, record) => void` | - | Tree expand/collapse callback. | | `onExpandedRowsChange` | `(expandedKeys) => void` | - | Tree expanded-keys callback. | | `transformCellText` | `(opt) => unknown` | - | Transform cell text; `opt` contains `text`, `column`, `record` and `index`. | | `showSorterTooltip` | `boolean` | `true` | Table-level sorter tooltip switch, overridable per column. | | `sortDirections` | [`SortOrder[]`](/guide/type-reference#sortorder) | - | Table-level sort direction list, used as the default for columns. | ### Custom structure | Prop | Type | Default | Description | | ----------------- | ------------------------------------------ | ------- | ---------------------------------------------------- | | `rowClassName` | `string \| RowClassName` | - | Extra class for body rows. | | `customRow` | `GetComponentProps` | - | Inject attributes, events and styles on body rows. | | `customHeaderRow` | `(columns, index?) => CellAdditionalProps` | - | Inject attributes, events and styles on header rows. | | `title` | `(data) => VNodeChild` | - | Table title render function. | | `footer` | `(data) => VNodeChild` | - | Table footer render function. | ## Column behavior ### Basics | Field | Type | Default | Description | | ------------ | -------------------------------------------------- | ------- | ----------------------------------------------------------------------------------- | | `key` | [`Key`](/guide/type-reference#key) | - | Unique column identity; passing it explicitly is recommended. | | `title` | `VNodeChild \| function` | - | Column title: text, VNode or render function. | | `dataIndex` | [`DataIndex`](/guide/type-reference#dataindex) | - | Data field path, e.g. `'name'` or `['address', 'city']`. | | `width` | `number \| string` | - | Column width; numbers are treated as px. | | `align` | [`AlignType`](/guide/type-reference#aligntype) | - | Cell content alignment. | | `ellipsis` | `boolean \| { showTitle?: boolean }` | `false` | Ellipsize overflowing cell content; `showTitle: false` disables the hover tooltip. | | `className` | `string` | - | Extra class for the column's cells. | | `colSpan` | `number` | - | Header cell colSpan. | | `visible` | `boolean` | `true` | Whether the column is shown, see [column display](/guide/column-display) (Chinese). | | `responsive` | [`Breakpoint[]`](/guide/type-reference#breakpoint) | - | Show the column when any listed breakpoint matches the screen. | ### Custom rendering | Field | Type | Default | Description | | ------------------ | ------------------------------------------------- | ------- | ------------------------------------------------------------------------ | | `customRender` | `(ctx) => VNodeChild \| RenderedCell` | - | Custom body cell content. Returning `RenderedCell` also sets cell props. | | `customCell` | `(record, index, column?) => CellAdditionalProps` | - | Inject attributes, events and styles on body cells. | | `customHeaderCell` | `(column, index) => CellAdditionalProps` | - | Inject attributes, events and styles on header cells. | ```ts customRender: ({ text, index }) => index === 0 ? { children: String(text), props: { colSpan: 2, style: { fontWeight: 'bold' } } } : String(text) ``` ### Fixed columns and resizing | Field | Type | Default | Description | | ----------- | --------------------------- | ------- | -------------------------------------------- | | `fixed` | `'left' \| 'right' \| true` | - | Fixed side; `true` equals `'left'`. | | `resizable` | `boolean` | `false` | Whether the column width is drag-adjustable. | | `minWidth` | `number` | `50` | Minimum width while resizing. | | `maxWidth` | `number` | - | Maximum width while resizing. | ### Sorting | Field | Type | Default | Description | | ------------------- | ------------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------- | | `sorter` | [`ColumnSorter`](/guide/type-reference#columnsorter) | - | Enable sorting: default compare, custom compare fn or multi-column object. | | `sortOrder` | [`SortOrder`](/guide/type-reference#sortorder) | - | Controlled sort order. | | `defaultSortOrder` | [`SortOrder`](/guide/type-reference#sortorder) | - | Uncontrolled default order, effective on first render only. | | `sortDirections` | `SortOrder[]` | `['ascend', 'descend']` | Sort directions available for this column. | | `showSorterTooltip` | `boolean` | inherits table config | Column-level sorter tooltip switch. | Table-level `sortDirections` and `showSorterTooltip` act as defaults; column-level config wins. ### Filtering | Field | Type | Default | Description | | ----------------------------------- | -------------------------------------------------------------- | -------- | -------------------------------------------------------------- | | `filters` | [`ColumnFilterItem[]`](/guide/type-reference#columnfilteritem) | - | Filter menu items; renders the filter icon in the header. | | `onFilter` | `(value, record) => boolean` | - | Filter function; return `true` to keep the row. | | `filterMultiple` | `boolean` | `true` | Whether multiple filter values can be picked. | | `filteredValue` | `Array \| null` | - | Controlled filter values. | | `defaultFilteredValue` | `Array` | - | Uncontrolled default filter values. | | `customFilterDropdown` | `boolean` | `false` | Use the table-level `customFilterDropdown` slot. | | `filterSearch` | `boolean \| (input, filter) => boolean` | `false` | Search within filter items. | | `filterMode` | `'menu' \| 'tree'` | `'menu'` | Filter item presentation mode. | | `filterResetToDefaultFilteredValue` | `boolean` | `false` | Reset restores the default filter values. | | `filterDropdownOpen` | `boolean` | - | Controlled filter dropdown visibility. | | `onFilterDropdownOpenChange` | `(visible) => void` | - | Filter dropdown visibility callback. | | `filtered` | `boolean` | - | Externally control the filter icon highlight; does not filter. | | `filterIcon` | `({ filtered }) => VNodeChild` | - | Custom filter icon. | | `filterDropdown` | `VNodeChild \| (props) => VNodeChild` | - | Column-level custom filter panel; overrides the table slot. | ### Column groups | Field | Type | Default | Description | | ---------- | -------------------------------------------------------- | ------- | ------------------------------------------------------------- | | `children` | `Array \| ColumnGroupType>` | - | Child columns. With `children` present the column is a group. | Column groups do not receive leaf-column behaviors such as sorting, filtering, `dataIndex` and `customRender`. ## Row Selection `rowSelection` enables the selection column: multiple, single, tree-linked, batch menus and controlled state. | Field | Type | Default | Description | | ------------------------- | ------------------------------------------------------------------ | ------------ | ------------------------------------------------ | | `type` | `'checkbox' \| 'radio'` | `'checkbox'` | Selection type. | | `selectedRowKeys` | `Key[]` | - | Controlled selected keys. | | `defaultSelectedRowKeys` | `Key[]` | - | Default selected keys. | | `onChange` | `(keys, rows) => void` | - | Selection change callback. | | `onSelect` | `(record, selected, rows) => void` | - | Single-row selection callback. | | `onSelectMultiple` | `(selected, rows, changeRows) => void` | - | Shift multi-select callback. | | `onSelectAll` | `(selected, rows, changeRows) => void` | - | Select-all callback. | | `onSelectInvert` | `(keys) => void` | - | Invert-selection callback. | | `onSelectNone` | `() => void` | - | Clear-selection callback. | | `getCheckboxProps` | `(record) => { disabled?, name? }` | - | Inject attributes on selection controls. | | `columnWidth` | `number \| string` | - | Selection column width. | | `fixed` | `boolean \| 'left' \| 'right'` | - | Fixed position of the selection column. | | `columnTitle` | `string \| VNodeChild` | - | Selection column header content. | | `renderCell` | `(value, record, index, originNode) => VNodeChild \| RenderedCell` | - | Custom selection cell. | | `checkStrictly` | `boolean` | `true` | Parent/child independent selection in tree data. | | `selections` | `boolean \| array` | `false` | Default or custom batch-selection menu. | | `hideSelectAll` | `boolean` | `false` | Hide the select-all checkbox and dropdown. | | `preserveSelectedRowKeys` | `boolean` | `false` | Keep selected keys when the data source changes. | Default batch-selection constants: see [SelectionSentinel](/guide/type-reference#selectionsentinel) (Chinese). ## Expandable `expandable` configures expandable row content. Tree-data expand props live at the `VTable` top level. | Field | Type | Default | Description | | ------------------------ | ------------------------------------------------- | ------- | ------------------------------------------------------- | | `expandedRowRender` | `(record, index, indent, expanded) => VNodeChild` | - | Expanded row content render function. | | `expandedRowKeys` | `Key[]` | - | Controlled expanded row keys. | | `defaultExpandedRowKeys` | `Key[]` | - | Default expanded row keys. | | `expandRowByClick` | `boolean` | `false` | Expand on full-row click. | | `expandIcon` | `(props) => VNodeChild` | - | Custom expand icon. | | `onExpand` | `(expanded, record) => void` | - | Expand/collapse callback. | | `onExpandedRowsChange` | `(expandedKeys) => void` | - | Expanded-keys callback. | | `columnWidth` | `number \| string` | - | Expand column width. | | `fixed` | `'left' \| 'right' \| true` | - | Fixed position of the expand column; `true` = `'left'`. | | `defaultExpandAllRows` | `boolean` | `false` | Expand all rows by default. | | `rowExpandable` | `(record) => boolean` | - | Whether a row is expandable. | | `showExpandColumn` | `boolean` | `true` | Whether to show the expand column. | | `expandedRowClassName` | `string \| RowClassName` | - | Class for expanded rows. | ## Events | Event | Payload | Description | | -------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- | | `change` | `(filters, sorter, extra)` | Unified event after sorting, filtering and selection. | | `resizeColumn` | `(column, width)` | Fired after a column resize drag ends. | | `rowDragEnd` | `(newData, info)` | Fired when row drag sorting finishes with a changed order, see [row drag sort](/guide/row-drag-sort) (Chinese). | `change` currently has no pagination payload. `extra.action` is `'sort'`, `'filter'` or `'select'`. ```ts function handleChange(filters, sorter, extra) { if (extra.action === 'sort') { // sync sort state or request remote data } } ``` ## Slots | Slot | Payload type | Description | | ---------------------- | ----------------------------------------------------------------------------------------------- | -------------------------------- | | `bodyCell` | [`TableBodyCellSlotProps`](/guide/type-reference#tablebodycellslotprops) | Custom cell content. | | `headerCell` | [`TableHeaderCellSlotProps`](/guide/type-reference#tableheadercellslotprops) | Custom header cell content. | | `empty` | `()` | Custom empty state. | | `loading` | `()` | Custom loading state. | | `customFilterDropdown` | [`CustomFilterDropdownSlotProps`](/guide/type-reference#customfilterdropdownslotprops) | Table-level custom filter panel. | | `customFilterIcon` | `{ column, filtered }` | Table-level custom filter icon. | | `title` | [`TableDataSlotProps`](/guide/type-reference#tabledataslotprops) | Custom title area. | | `footer` | [`TableDataSlotProps`](/guide/type-reference#tabledataslotprops) | Custom footer area. | | `summary` | `()` | Custom summary area. | > These are Vue slots. To restyle structure via classes, see the [ui slot reference](/guide/ui-slots-reference) (Chinese). ## VTableSummary `VTableSummary` renders summary rows. | Component | Common props | Description | | -------------------- | -------------------------------------- | --------------------------------------------------------------- | | `VTableSummary` | `fixed` | Summary container; `fixed` accepts `true`, `'top'`, `'bottom'`. | | `VTableSummary.Row` | - | Summary row. | | `VTableSummary.Cell` | `index`, `colSpan`, `rowSpan`, `align` | Summary cell. | ## Related pages - [Type reference](/guide/type-reference) (Chinese) - [ui slot reference](/guide/ui-slots-reference) (Chinese) - [Sorting](/guide/sorting) (Chinese) - [Filtering](/guide/filtering) (Chinese) --- # Getting started This page does one thing: get your first vtable-guild table running in an existing Vue 3 + Vite project as quickly as possible. If you are already using ant-design-vue or element-plus, finish the initialization here first, then continue with the migration and theming pages (currently Chinese-only). ## Requirements - Node `^20.19.0` or `>=22.12.0` - pnpm `>=10.28.0` - Vue `^3.5.0` - Vite `^5` or newer ## Install The component does not require Tailwind CSS in the host project. Install the package: ```bash pnpm add @vtable-guild/vtable-guild ``` ## Configure the style entry vtable-guild supports three style modes: `prebuilt`, `tailwind3` and `tailwind4`. ### prebuilt If your project does not use Tailwind CSS, import the prebuilt stylesheet entry directly. For example, in `src/main.css`: ```css @import '@vtable-guild/vtable-guild/css/style'; ``` This entry ships pre-generated utilities for the library's internal styles. You do not need to install Tailwind CSS, configure `@tailwindcss/vite`, or scan this library's sources. ### tailwind3 If your project uses Tailwind CSS 3, use the Tailwind 3 entry and add the library's preset to your Tailwind config: ```js import vtableGuildTailwind3Preset from '@vtable-guild/vtable-guild/tailwind3-preset' export default { content: [ './index.html', './src/**/*.{vue,ts,tsx,js,jsx}', './node_modules/@vtable-guild/**/*.{js,mjs}', ], presets: [vtableGuildTailwind3Preset], } ``` ```css @import '@vtable-guild/vtable-guild/css/tailwind3'; @tailwind base; @tailwind components; @tailwind utilities; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind3' })) ``` ### tailwind4 If your project uses Tailwind CSS 4, use the Tailwind 4 entry: ```bash pnpm add -D tailwindcss @tailwindcss/vite ``` ```ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [vue(), tailwindcss()], }) ``` ```css @import 'tailwindcss'; @import '@vtable-guild/vtable-guild/css/tailwind4'; ``` ```ts app.use(createVTableGuild({ cssMode: 'tailwind4' })) ``` `@vtable-guild/vtable-guild/css/style`, `@vtable-guild/vtable-guild/css/tailwind3` and `@vtable-guild/vtable-guild/css/tailwind4` all include: - the default `antdv` preset - the `element-plus` preset - theme tokens - the base styles required by the components Switching presets requires no extra CSS. In prebuilt mode the library's internal utility classes are emitted with the `vtg-` prefix. In Tailwind 3/4 modes internal classes stay unprefixed. See [package consumption](/guide/package-consumption) (Chinese) for the full rules. ## Initialize the plugin Import the global stylesheet and initialize the plugin in your entry file. For example, in `src/main.ts`: ```ts import { createApp } from 'vue' import App from './App.vue' import { createVTableGuild } from '@vtable-guild/vtable-guild' import './main.css' const app = createApp(App) app.use(createVTableGuild()) app.mount('#app') ``` The default preset is `antdv`. To switch to the element-plus look, set `themePreset`: ```ts app.use( createVTableGuild({ themePreset: 'element-plus', }), ) ``` ## Minimal example ```vue ``` ## Where to go next - To estimate migration cost: read [migrating from ant-design-vue](/guide/migration-from-antd) (Chinese) - To unify the visual system: [three-layer theme overrides](/guide/theme-overrides) and [Table CSS variables](/guide/theme-tokens) (Chinese) - To inspect the full API: the [English API Reference](/en/guide/api-reference) --- # Guide This guide is for developers who already use ant-design-vue or element-plus in a Vue 3 project. It focuses on whether replacing your current table is worth it, how to integrate vtable-guild, and how to use it in high-frequency scenarios. English coverage is expanding. The pages below are available in English; the rest of the guide is in the [Chinese documentation](/guide/). ## Available in English - [Getting started](/en/guide/getting-started) — install, pick a style mode and initialize the plugin. - [API Reference](/en/guide/api-reference) — props, column fields, events, slots and the summary components.