--- title: Table 表格 description: 高性能虚拟滚动表格,支持排序、固定列、多选、行内编辑、列宽 / 列序拖拽与行拖拽排序 --- # Table 表格 `Table` 用于展示结构化数据,底层是 [`stk-table-vue`](https://ja-plus.github.io/stk-table-vue/),虚拟滚动 / 列宽拖拽 / 列序拖拽 / 区域选择 / 行拖拽排序都由它提供;组件负责**性能门控**、**内部列管理**与**行内编辑态**。 ## 何时使用 - 数据量大(成百上千行)且需要滚动流畅时; - 需要行内编辑、多选批量操作、列宽 / 列序可调时; - 数据量很小、只要一张静态表时,原生 `` 或 [Grid](/ui/general/grid) 更轻。 ## 基础用法 给 `columns` 与 `dataSource` 两份数据即可。序号列(`seq`)默认开启,外框与圆角默认有(`bordered`)。 ## 虚拟滚动与性能 组件内置两条门控,**自动**决定是否启用虚拟滚动,不需要业务手动切换: | 方向 | 阈值 | 低于阈值时 | 原因 | | --- | --- | --- | --- | | 纵向 | 行数 > 100 | 全量渲染 | 库的虚拟滚动在「行数略多于单屏行数」时会把最后几行算出视口外,必须滚动才可见;行数少时全量渲染没有性能代价,却换来确定性正确的渲染 | | 横向 | 列数 > 20 | 关掉横向虚拟 | 库在横向虚拟开启时会把每列宽度钉死为 `minWidth ?? width ?? 100`,未设 `width` 的列会失去「按比例铺满容器」的原生自适应 | 可以用 `virtual` / `virtualX` 关掉,但**不能**把它们强制打开到阈值以下。 除了门控,还有三处性能相关设计: - **无编辑行时不注入 `customCell`**:纯展示列与非编辑态的可编辑列走库的原生 `td` 渲染路径,滚动时每格少一个函数式组件实例; - **尺寸变化 150ms 防抖**:折叠动画 / 窗口缩放期间 ResizeObserver 每帧都会通知,逐帧重算会强制 reflow 并重渲染可见行列;组件合并到尺寸稳定后只刷新一次,并区分「仅宽度变化」只重算横向; - **选择列用原生 ``**:视觉由 CSS 模拟成 [Checkbox](/ui/form/checkbox) 的外观,但每行不创建组件实例。 ## 多选与批量操作 传 `rowSelection` 即在最前注入选择列;`getCheckboxProps` 可禁用个别行(禁用行不计入「全选」的分母)。 ## 排序 列上写 `sorter: true` 即可点表头排序(组件内排序,不请求接口)。`sortType` 决定按数字还是字符串比较,默认字符串;需要自定义规则时 `sorter` 也可以传函数。 ## 行内编辑 列上加 `editor` 即可编辑:单击单元格进入,`Enter` 确认、`Esc` 取消。 | 编辑器类型 | 说明 | | --- | --- | | `text` / `number` / `textarea` | 用 [Input](/ui/form/input) 渲染 | | `select` | 用 [Select](/ui/form/select) 渲染;`options` 可以是数组,也可以是接收当前行的函数 | | `checkbox` | 点击即切换,无需先激活整行;约定 `1` = 选中、`0` = 未选中(与后端 tinyint 对齐) | 编辑器的输入值先写进内部草稿,**失焦才落库并抛出 `change`**。这样每敲一个字符不会触发父级重渲染(否则光标会丢、输入法会断)。用 `editable={false}` 可整体禁用编辑。 ## 操作列 列上加 `actions` 渲染成一排小按钮;`type: 'more'` 的项会收进「更多」下拉。带 `confirm` 的操作先弹确认框,确认后才执行 `onClick`。 操作列建议显式写 `resizable: false`:它的宽度由内容决定,拖了不会落库,列一重建就丢。 ## 列宽、列序与行拖拽 列宽 / 列序拖拽要求用 `v-model:columns` 绑定列定义——否则组件拖完无处回写(松手回弹),会直接关掉这两个功能。行拖拽排序用 `row-draggable`,顺序变化通过 `row-order-change` 回传。 ## API ### Props | 名称 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | `columns` | `G3TableColumn[]` | `[]` | 列定义,配合 `v-model:columns` 接收拖拽后的回写 | | `dataSource` | `T[]` | `[]` | 数据源 | | `rowKey` | `string \| (row) => string \| number` | `'id'` | 行唯一键 | | `virtual` | `boolean` | `true` | 纵向虚拟滚动总开关(实际是否开启受行数门控) | | `virtualX` | `boolean` | `true` | 横向虚拟滚动总开关(实际是否开启受列数门控) | | `rowHeight` | `number` | `30` | 行高,同时驱动虚拟滚动计算 | | `headerRowHeight` | `number` | `34` | 表头行高 | | `bordered` | `boolean \| string` | `true` | 外框圆角描边 + 行分隔线;`false` 时只留行分隔线 | | `colResizable` | `boolean \| object` | `true` | 列宽拖拽;未绑定 `v-model:columns` 时自动关闭。可用 `{ disabled: (col) => boolean }` 按列禁用 | | `columnDraggable` | `boolean \| object` | `true` | 列序拖拽;同上要求绑定 `v-model:columns` | | `rowDraggable` | `boolean` | `false` | 行拖拽排序 | | `rowSelection` | `TableRowSelection \| null` | `null` | 多选配置,见下 | | `seq` | `boolean \| { title?, width? }` | `true` | 序号列 | | `activeRowKey` | `string \| number \| null` | `null` | 当前高亮行 | | `editable` | `boolean` | `true` | 行内编辑总开关 | | `noDataFull` | `boolean` | `true` | 空态铺满容器高度 | | `showOverflow` | `boolean` | `true` | 内容溢出省略 | | `autoFitWidth` | `boolean` | `false` | 非横向虚拟时铺满容器宽度(开启后关闭列宽拖拽) | | `theme` | `'light' \| 'dark'` | — | 不传则跟随全局主题(`ConfigProvider` / `html[data-g3-theme]`) | | `footerData` | `T[]` | `[]` | 表尾数据 | | `footerConfig` | `object` | `` | 表尾配置 | ### 列定义 `G3TableColumn` 在 `stk-table-vue` 的列类型基础上扩展;下面只列自有字段,其余(`width` / `minWidth` / `fixed` / `align` / `headerAlign` / `sorter` / `sortType` / `children` / `mergeCells` 等)原样透传。 | 字段 | 类型 | 说明 | | --- | --- | --- | | `dataIndex` | `keyof T & string` | 取值字段 | | `title` | `string` | 表头文字 | | `resizable` | `boolean` | 该列是否可拖宽;操作列 / 展开列建议设 `false` | | `editor` | `TableEditor` | 行内编辑器,见下 | | `actions` | `TableAction[]` | 操作列按钮 | | `customCell` | `(props) => VNode \| string` | 自定义单元格渲染(逃生舱),传了就不再自动包装 | ### `editor` | 字段 | 类型 | 说明 | | --- | --- | --- | | `type` | `'text' \| 'number' \| 'password' \| 'textarea' \| 'select' \| 'checkbox'` | 编辑器类型 | | `options` | `TableSelectOption[] \| ((row) => TableSelectOption[])` | select 选项,可依赖当前行其它字段 | | `disabled` | `boolean \| ((row) => boolean)` | 是否禁用该格编辑 | | `allowClear` | `boolean` | select 是否可清空,默认 `true` | | `emptyValue` | `unknown` | select 清空后落库的值,默认 `null` | | `onChange` | `(value, row, col) => void` | 本列值变化回调(早于组件的 `change`) | ### `actions` | 字段 | 类型 | 说明 | | --- | --- | --- | | `key` | `string \| number` | 唯一键;`type: 'more'` 的子项用它做下拉 key | | `label` | `string` | 文案 | | `type` | `'default' \| 'danger' \| 'delete' \| 'more'` | 语义类型 | | `icon` | `Component` | 图标组件 | | `visible` | `boolean \| ((row) => boolean)` | 是否显示 | | `disabled` | `boolean \| ((row) => boolean)` | 是否禁用 | | `confirm` | `string \| object` | 二次确认;字符串为标题,对象支持 `title` / `description` / `okText` / `cancelText` / `okType` / `width` / `maskClosable` | | `onClick` | `(row) => void` | 点击回调(带 `confirm` 时在确认后执行) | | `items` | `TableAction[]` | `type: 'more'` 时的子项 | ### Events | 名称 | 参数 | 说明 | | --- | --- | --- | | `update:columns` | `(columns)` | 列宽 / 列序拖拽后回写(内部列已剥离) | | `update:selectedRowKeys` | `(keys)` | 勾选变化 | | `change` | `(row, col, value)` | 行内编辑的值变化 | | `row-order-change` | `(rows, sourceIndex, targetIndex)` | 行拖拽排序完成 | | `area-selection-change` | `(ranges)` | 单元格选区变化(行内编辑依赖它) | ### Exposed | 名称 | 类型 | 说明 | | --- | --- | --- | | `scrollToRow(rowKey)` | `Promise` | 滚动到指定行 | | `editRow(rowKey, focusCol?)` | `Promise` | 滚动到指定行并进入编辑 | | `initVirtualScroll()` / `refreshLayout()` | — | 手动重算虚拟滚动布局 | | `getSelectedArea()` / `clearSelectedArea()` | — | 读取 / 清空单元格选区 | | `setRowExpand(...)` | — | 展开 / 收起行(需配 `expand` 列) | ### Slots | 名称 | 说明 | | --- | --- | | `empty` | 空态内容,默认显示「暂无数据」 | | `expand` | 展开行内容(需列配置 `type: 'expand'`) | ## 实现说明 - **底层是 `stk-table-vue`**:虚拟滚动、列宽 / 列序拖拽、区域选择、行拖拽、二级表头、固定列、合并单元格都由它实现。组件不重复造这些轮子,只做门控与适配。 - **库样式已并入 `dist/style.css`**:库的 CSS 是独立文件(其 JS 里不含任何 `.css` import),组件 `@use` 了它,消费方不需要额外引一次第三方样式。 - 注意 SCSS 里**不能**写 `@use 'stk-table-vue/lib/style.css'`:带 `.css` 后缀时 Sass 不会内联,只原样输出一条 CSS `@import` 语句,产物里会留下一条浏览器解析不了的裸包路径。去掉后缀才会真正内联。 - **主题通过覆盖库的 CSS 变量实现**:库把 41 个主题值都做成了 `.stk-table` 作用域内的变量,组件把它们映射到 `--g3-*` 令牌(覆盖层在 `src/table/style/_overrides.scss`)。改变量而不是逐个选择器改样式,库升级时不容易失效。 - **区域选择按需自注册**:库的单元格区域选择是全局注册的(`registerFeature(useAreaSelection)`),不注册则 `area-selection-change` 永不触发、行内编辑失效。组件库不拥有 app 启动流程,因此**首次挂载时自动注册一次**;需要显式控制时可调用导出的 `registerTableFeatures()`。 - **`data-testid` 透传到内层**:组件 `inheritAttrs: false`,`$attrs` 落在内层 `StkTable` 上。外框 / 圆角在我们自己的根节点 `.g3-table` 上,写 E2E 时按类名定位根节点。 - **行编辑态存在 `WeakMap` 里**:按行对象存,不给业务数据打标记;行被回收时状态自动释放。行与行之间切换编辑**不翻转** `editingActive`,避免整表列重建。 - **RTL**:布局用逻辑属性,带符号位移走 `--g3-dir-sign`;分隔条拖拽与键盘方向由库的 `useDirection` 处理。