11 KiB
title, description
| title | description |
|---|---|
| Table 表格 | 高性能虚拟滚动表格,支持排序、固定列、多选、行内编辑、列宽 / 列序拖拽与行拖拽排序 |
Table 表格
Table 用于展示结构化数据,底层是 stk-table-vue,虚拟滚动 / 列宽拖拽 / 列序拖拽 / 区域选择 / 行拖拽排序都由它提供;组件负责性能门控、内部列管理与行内编辑态。
何时使用
- 数据量大(成百上千行)且需要滚动流畅时;
- 需要行内编辑、多选批量操作、列宽 / 列序可调时;
- 数据量很小、只要一张静态表时,原生
<table>或 Grid 更轻。
基础用法
给 columns 与 dataSource 两份数据即可。序号列(seq)默认开启,外框与圆角默认有(bordered)。
虚拟滚动与性能
组件内置两条门控,自动决定是否启用虚拟滚动,不需要业务手动切换:
| 方向 | 阈值 | 低于阈值时 | 原因 |
|---|---|---|---|
| 纵向 | 行数 > 100 | 全量渲染 | 库的虚拟滚动在「行数略多于单屏行数」时会把最后几行算出视口外,必须滚动才可见;行数少时全量渲染没有性能代价,却换来确定性正确的渲染 |
| 横向 | 列数 > 20 | 关掉横向虚拟 | 库在横向虚拟开启时会把每列宽度钉死为 minWidth ?? width ?? 100,未设 width 的列会失去「按比例铺满容器」的原生自适应 |
可以用 virtual / virtualX 关掉,但不能把它们强制打开到阈值以下。
除了门控,还有三处性能相关设计:
- 无编辑行时不注入
customCell:纯展示列与非编辑态的可编辑列走库的原生td渲染路径,滚动时每格少一个函数式组件实例; - 尺寸变化 150ms 防抖:折叠动画 / 窗口缩放期间 ResizeObserver 每帧都会通知,逐帧重算会强制 reflow 并重渲染可见行列;组件合并到尺寸稳定后只刷新一次,并区分「仅宽度变化」只重算横向;
- 选择列用原生
<input type="checkbox">:视觉由 CSS 模拟成 Checkbox 的外观,但每行不创建组件实例。
多选与批量操作
传 rowSelection 即在最前注入选择列;getCheckboxProps 可禁用个别行(禁用行不计入「全选」的分母)。
排序
列上写 sorter: true 即可点表头排序(组件内排序,不请求接口)。sortType 决定按数字还是字符串比较,默认字符串;需要自定义规则时 sorter 也可以传函数。
行内编辑
列上加 editor 即可编辑:单击单元格进入,Enter 确认、Esc 取消。
| 编辑器类型 | 说明 |
|---|---|
text / number / textarea |
用 Input 渲染 |
select |
用 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<T>[] |
[] |
列定义,配合 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<T>
在 stk-table-vue 的列类型基础上扩展;下面只列自有字段,其余(width / minWidth / fixed / align / headerAlign / sorter / sortType / children / mergeCells 等)原样透传。
| 字段 | 类型 | 说明 |
|---|---|---|
dataIndex |
keyof T & string |
取值字段 |
title |
string |
表头文字 |
resizable |
boolean |
该列是否可拖宽;操作列 / 展开列建议设 false |
editor |
TableEditor<T> |
行内编辑器,见下 |
actions |
TableAction<T>[] |
操作列按钮 |
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<T>[] |
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<void> |
滚动到指定行 |
editRow(rowKey, focusCol?) |
Promise<void> |
滚动到指定行并进入编辑 |
initVirtualScroll() / refreshLayout() |
— | 手动重算虚拟滚动布局 |
getSelectedArea() / clearSelectedArea() |
— | 读取 / 清空单元格选区 |
setRowExpand(...) |
— | 展开 / 收起行(需配 expand 列) |
Slots
| 名称 | 说明 |
|---|---|
empty |
空态内容,默认显示「暂无数据」 |
expand |
展开行内容(需列配置 type: 'expand') |
实现说明
- 底层是
stk-table-vue:虚拟滚动、列宽 / 列序拖拽、区域选择、行拖拽、二级表头、固定列、合并单元格都由它实现。组件不重复造这些轮子,只做门控与适配。 - 库样式已并入
dist/style.css:库的 CSS 是独立文件(其 JS 里不含任何.cssimport),组件@use了它,消费方不需要额外引一次第三方样式。- 注意 SCSS 里不能写
@use 'stk-table-vue/lib/style.css':带.css后缀时 Sass 不会内联,只原样输出一条 CSS@import语句,产物里会留下一条浏览器解析不了的裸包路径。去掉后缀才会真正内联。
- 注意 SCSS 里不能写
- 主题通过覆盖库的 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处理。