GridView 数据表格
通用布局能力:
DataGridOptions继承RenderBoxOptions,表格可直接配置width、height、min/max、margin和槽位对齐,也可在创建后赋值;这些属性不再由 GridView 维护第二套状态。详见组件通用布局属性。
RenderDataGrid 用于展示、选择、编辑和管理结构化行列数据。它是数据类页面的主力组件,适合查询结果、明细表、可编辑表格、分组汇总、大数据虚拟滚动和列状态持久化。
何时使用
- 需要展示二维表格数据,并支持行选择、单元格选择或范围选择。
- 需要可编辑单元格、下拉编辑、日期编辑、树形下拉、树表下拉或校验。
- 需要排序、过滤、快速过滤、分组、汇总和列菜单。
- 需要固定列、拖拽调整列宽、列顺序调整、列显示状态持久化。
- 需要在大量数据下保持可视行绘制和滚动性能。
何时不要使用
- 只展示少量静态表格,优先使用 Table。
- 数据有父子层级并且要在表格中展开折叠,优先使用 TreeGrid。
- 只需要键值型表单布局,优先使用 EntryGrid 或 FormPanel。
- 单列列表、菜单或卡片列表,优先使用 ListView 或 ItemsControl。
API 总览
主类:
RenderDataGrid<T extends Record<string, any>>
核心配置类型:
DataGridOptions<T>GridColumnDef<T>GridColumnEditorDef<T>GridSelectionState<T>GridSelectionChangeEvent<T>GridSelectionOptionsGridViewPreset
常用辅助类型:
GridColumnBaseGridColumnTextGridColumnNumberGridColumnCheckboxGridColumnSelectGridColumnSelectGridGridColumnDateGridColumnCustomGridSortDescriptorGridFilterRuleGridGroupDefGridSummaryDefGridColumnStateGridColumnFilterStateGridCellValidationArgsGridCellValidationResultGridRowValidationArgsGridRowValidationResultGridValidationResultGridRowStyleArgsGridCellStyleArgsGridCellDisplayTextArgsGridCellContext<T>GridCellEditPolicyGridCellEditState
这些类型都从 ds-ui 包入口导出。
最小示例
import { RenderDataGrid, type GridColumnDef } from 'ds-ui' interface PatientRow { id: string name: string gender: string age: number} const columns: GridColumnDef<PatientRow>[] = [ { key: 'name', title: '姓名', type: 'text', width: 120, sortable: true, filterable: true }, { key: 'gender', title: '性别', type: 'select', width: 80, sortable: true, filterable: true, options: [ { value: 'M', label: '男' }, { value: 'F', label: '女' }, ] }, { key: 'age', title: '年龄', type: 'number', width: 80, align: 'right', sortable: true, filterable: true },] const grid = new RenderDataGrid<PatientRow>({ rowKey: 'id', columns, rows: [ { id: 'p1', name: '李安然', gender: 'F', age: 36 }, ], selectionMode: 'row', sortable: true, editable: true, onCellChange: (row, key, value) => { ;(row as any)[key] = value },})
构造参数
new RenderDataGrid<T>(options: DataGridOptions<T>)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
columns |
GridColumnDef<T>[] |
必填 | 列定义。列的顺序决定默认显示顺序。 |
rows |
T[] |
必填 | 源数据行。排序、过滤、分组会生成可视行,但不会复制业务对象;替换 rows 会按重新绑定处理。 |
rowKey |
keyof T & string | (row: T) => GridRowId | null | undefined |
undefined |
可选行唯一键。默认按行对象引用识别行;只有在替换 rows 且行对象会被重建时,才需要 rowKey 用于恢复选择和校验错误。 |
groupBy |
GridGroupDef<T>[] |
[] |
分组配置。支持多级分组。 |
defaultGroupExpanded |
boolean |
true |
初始分组是否展开。 |
sort |
GridSortDescriptor[] |
[] |
初始多列排序。 |
filters |
GridFilterRule[] |
[] |
初始结构化过滤规则。 |
quickFilter |
string |
'' |
初始快速过滤文本。 |
summary |
GridSummaryDef<T>[] |
[] |
页脚汇总定义。 |
dataState |
'ready' | 'loading' | 'empty' | 'error' |
'ready' |
数据状态。非 ready 时停止主体交互并显示状态信息。 |
stateMessage |
string |
'' |
loading、empty、error 状态下显示的文本。 |
selectionMode |
'row' | 'cell' | 'range' |
'row' |
选择模式。 |
rangeSelectionAutoScroll |
boolean |
true |
范围拖选到边缘时是否自动滚动。 |
width / height |
number |
undefined |
来自 RenderBoxOptions 的期望尺寸。 |
minWidth / maxWidth |
number |
undefined |
水平方向尺寸边界。 |
minHeight / maxHeight |
number |
undefined |
垂直方向尺寸边界。 |
margin |
EdgeInsetsInput |
0 |
组件外部留白。 |
horizontalAlignment / verticalAlignment |
BoxAlignment |
undefined |
组件在父布局槽位中的对齐方式。 |
footerHeight |
number |
有汇总时 28,否则 0 |
页脚高度。显式设置后不再随 summary 自动切换。 |
filterRowVisible |
boolean |
false |
是否显示过滤行。 |
filterRowHeight |
number |
28 |
过滤行高度。 |
rowHeight |
number |
viewport 默认值 | 数据行高度。 |
headerHeight |
number |
viewport 默认值 | 表头高度。 |
cellTextOverflow |
'clip' | 'ellipsis' |
'ellipsis' |
单元格文本溢出策略。 |
validateCell |
(args) => GridCellValidationResult |
undefined |
单元格提交时校验。返回 false、字符串或 { valid:false } 会阻止提交。 |
validateRow |
(args) => GridRowValidationResult<T> |
undefined |
全表验证时执行行级字段关联校验;返回以列 key 为键、错误文本为值的对象。 |
onCellChange |
(row, key, value) => void |
undefined |
单元格值提交成功后触发。通常在这里写回业务状态。 |
onRowClick |
(row, event) => void |
undefined |
行被点击后触发。 |
onRowActivate |
(row, event) => void |
undefined |
行被激活后触发,通常来自双击或键盘确认。 |
onSelectionChange |
(event) => void |
undefined |
选择状态变化后触发。 |
onCurrentCellChange |
(cell) => void |
undefined |
当前单元格变化后触发。 |
onFocusedCellChange |
(cell) => void |
undefined |
焦点单元格变化后触发。 |
onScrollChange |
(scrollY) => void |
undefined |
纵向滚动变化后触发。 |
disabled |
boolean |
false |
是否整体禁用。禁用后不参与焦点导航,并阻断 pointer、keyboard、popup、drag 和复制。 |
readonly |
boolean |
false |
是否只读。只读仍允许选择、复制、滚动、排序和过滤,但阻止编辑、粘贴和删除。 |
editable |
boolean |
false |
全局是否允许编辑。必须为 true 才能进入编辑;列可用 editable:false 进一步禁用。 |
resizableColumns |
boolean |
true |
是否允许拖拽列宽。 |
autoFitColumns |
boolean |
false |
是否允许双击列边界自动适配列宽。 |
sortable |
boolean |
true |
是否启用排序。列仍需配置 sortable: true 才可点击表头排序。 |
reorderableColumns |
boolean |
true |
是否允许拖拽调整列顺序。固定列不能被拖拽,也不能与非固定列互换区域。 |
reserveScrollbars |
boolean |
viewport 默认值 | 是否预留滚动条空间,避免滚动条出现时布局跳动。 |
getCellDisplayText |
(args) => string | null | undefined |
undefined |
自定义单元格显示文本。返回空值时使用默认文本。 |
getGroupDisplayText |
(args) => string | null | undefined |
undefined |
自定义分组行文本。 |
resolveRowStyle |
(args) => GridRowStyleOverride | null | undefined |
undefined |
自定义行样式。 |
resolveCellStyle |
(args) => GridCellStyleOverride | null | undefined |
undefined |
自定义单元格样式。 |
resolveCellEditPolicy |
(context: GridCellContext<T>) => GridCellEditPolicy | null | undefined |
undefined |
按当前行和列解析用户编辑权限、Tab 停靠和不可编辑原因。 |
列配置
所有列共享 GridColumnBase 字段:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
key |
string |
必填 | 数据字段名,也是列状态、排序、过滤、编辑定位的关键字段。 |
title |
string |
必填 | 表头显示文本。 |
width |
number |
内部默认宽度 | 初始列宽。 |
minWidth |
number |
checkbox 为 52,其他为 40 |
最小列宽,用于拖拽和自动列宽。 |
fixed |
boolean |
false |
兼容字段。true 等价于左固定列。 |
pinned |
'left' | 'right' | false |
fixed ? 'left' : false |
固定列位置。 |
hidden |
boolean |
false |
是否隐藏。隐藏列仍保留在 columns 中。 |
widthMode |
'fixed' | 'interactive' | 'stretch' | 'autoContent' |
'interactive' |
列宽模式。autoContent 会测量内容,需注意性能。 |
align |
'left' | 'center' | 'right' |
按列类型决定 | 单元格文本对齐。 |
cellTextOverflow |
'clip' | 'ellipsis' |
继承表格配置 | 当前列文本溢出策略。 |
editable |
boolean |
继承表格配置 | 当前列是否可编辑。 |
sortable |
boolean |
false |
当前列是否可排序。表格的 sortable 是全局开关,列仍需显式设置 sortable: true。 |
filterable |
boolean |
false |
当前列是否显示过滤入口或参与过滤行。 |
filterValueFormatter |
(value, row, defaultDisplayText) => string | null | undefined |
undefined |
自定义值筛选候选项文本。默认使用列类型的无装饰显示文本,不复用 getCellDisplayText 添加的图标或状态前缀。 |
editor |
GridColumnEditorDef |
根据 type 推断 |
显式指定编辑器,覆盖列类型默认编辑器。 |
列类型:
| 类型 | 额外字段 | 说明 |
|---|---|---|
GridColumnText |
type:'text', placeholder?: string |
文本列,默认使用文本输入编辑器。 |
GridColumnNumber |
type:'number', min?, max?, step?, decimals? |
数字列。编辑态显示上下步进按钮,step 默认按 1 处理。 |
GridColumnCheckbox |
type:'checkbox' |
布尔列。 |
GridColumnSelect |
type:'select', options, searchable? |
下拉选择列,options 使用 Dropdown 选项结构。 |
GridColumnSelectGrid |
type:'select-grid', columns, rows, valueKey, labelKey, searchable? |
表格下拉选择。简单场景可直接使用;复杂场景建议使用 editor.kind='lookup'。 |
GridColumnDate |
type:'date', showTime? |
日期或日期时间列。 |
GridColumnCustom |
type:'custom', render, renderColor? |
自定义显示列。默认没有内置编辑器。 |
左、右固定列与普通滚动列之间会持续绘制强分隔线和轻阴影。横向滚动使内容进入固定区域下方时,对应方向的阴影会自动增强;滚动到边缘后恢复为轻阴影。该视觉覆盖表头、过滤行、数据区和汇总区,不需要额外配置。
编辑器配置
GridColumnEditorDef 用于覆盖列的默认编辑器。
| kind | 字段 | 说明 |
|---|---|---|
text |
placeholder? |
文本输入。 |
number |
无额外字段 | 数字输入。编辑态右侧显示上下步进按钮,也可使用 ArrowUp、ArrowDown 调整。 |
checkbox |
无额外字段 | 布尔值编辑。 |
select |
options, searchable? |
单选下拉。 |
lookup |
columns, rows, valueKey, labelKey, searchable?, queryKeys?, metaKey?, queryProcessor? |
表格查找下拉。 |
date |
showTime? |
日期或日期时间选择。 |
drop-tree |
roots, searchable?, expandAllOnOpen?, expandedKeysOnOpen?, queryTextBuilder?, queryProcessor? |
树形下拉。关联 DropTreeEdit。 |
drop-tree-grid |
columns, roots, treeColumnKey, labelKey, searchable?, metaKey?, metaFormatter?, expandAllOnOpen?, expandedKeysOnOpen?, queryTextBuilder?, queryProcessor? |
树表下拉。关联 DropTreeGridEdit。 |
编辑流程:
- 鼠标双击、键盘编辑或 API 调用
beginEdit()进入编辑。 - 输入控件修改临时文本或临时值。
commitEdit()或编辑器确认时触发校验。- 校验通过后触发
onCellChange(row, key, value)。 - 业务代码在
onCellChange中更新源对象或外部状态。
数字步进
number 编辑器在当前单元格进入编辑状态后显示上下步进按钮。步进只更新当前编辑草稿,仍然在 Enter、Tab、失焦或显式 commitEdit() 时统一校验和提交,不会在每次点击按钮时直接触发 onCellChange。
interface OrderRow { dose: number} const columns: GridColumnDef<OrderRow>[] = [ { key: 'dose', title: '剂量', type: 'number', min: 0, max: 100, step: 0.5, decimals: 1, },]
- 点击上、下按钮分别增加或减少一个
step;step只有在有限且大于0时生效,否则统一按1处理。配置decimals后,step会先对齐到相同的小数精度;如果结果为0,则使用一个最小显示单位(10^-decimals),保证每次点击都能产生可见且可逆的变化。 decimals会先截断为整数,再限制在0到100;非有限值按未配置处理。min、max也只接受有限值,非有限边界会被忽略;当同时配置且min > max时,这组冲突边界不会参与归一化。- 按钮步进和最终提交共用同一套数值归一化。命中或越过有效的
min、max时,边界值本身是稳定结果;其余数值先按decimals取小数位,再限制到有效边界内。即使边界无法用指定小数位精确表示,按钮显示的草稿在提交时也不会再次变成另一个值。 - 一次按压只属于发起它的指针和当时的编辑会话。只有同一指针在同一会话、同一按钮内完成释放才会步进;在原按钮外释放、滚动表格、取消指针或切换编辑会话都不会修改草稿。
- 连续快速点击步进按钮只按点击次数步进,不会触发单元格双击编辑,也不会因单元格双击逻辑重新全选输入文本;步进后光标位于新文本末尾。
- 数字编辑状态下,
ArrowUp、ArrowDown与按钮行为一致;非编辑状态下仍用于表格行导航。 - 空草稿从
0开始步进,再应用小数位和边界;当前文本不是完整有效数字时不会执行步进,也不会覆盖用户正在修正的内容。 - 有效小数步进使用十进制定点加减,避免
0.2 + 0.1一类常见浮点残差。 - 数字步进不响应鼠标滚轮,避免滚动表格时意外修改业务数据。
输入校验
Grid 校验只负责输入值是否合法,不负责业务提交、后台保存或服务端状态。
- number 编辑器会拒绝
12abc、NaN、Infinity等非完整有限数字,不会截取数字前缀或静默写回旧值。 - date 编辑器会拒绝无法解析或不存在的 ISO 日期。
validateCell负责单字段规则,在单元格提交、程序化setCellValue()和全表validate()时执行。validateRow负责同一行字段之间的关联规则,只在显式调用validate()时执行。返回对象的 key 必须对应列 key,错误会显示在对应单元格。GridRowValidationArgs.sourceRowIndex是该行在原始rows数组中的索引,不是排序、过滤或分组后的可视索引;业务身份优先使用row或rowId。validate()会先尝试提交活动编辑器,然后验证全部源数据行和全部列,包括被筛选掉的行与隐藏列;不会修改合法数据。- 校验错误沿用单元格错误边框,hover 显示错误文本。
focusFirstError()只定位当前可见且列未隐藏的第一个错误。
import { RenderDataGrid, type GridColumnDef } from 'ds-ui' interface OrderRow { itemCode: string amount: number unitCode: string} const columns: GridColumnDef<OrderRow>[] = [ { key: 'itemCode', title: '项目', type: 'text', editable: true }, { key: 'amount', title: '数量', type: 'number', editable: true }, { key: 'unitCode', title: '单位', type: 'text', editable: true },]const rows: OrderRow[] = [] const grid = new RenderDataGrid<OrderRow>({ columns, rows, validateCell: ({ key, value }) => { if (key === 'itemCode' && !value) return '请选择项目' return true }, validateRow: ({ row }) => { if (row.amount > 0 && !row.unitCode) { return { unitCode: '请输入单位' } } return undefined },}) const result = grid.validate()if (!result.valid) grid.focusFirstError()
GridValidationResult<T> 返回 { valid, errors };errors 与 getCellErrors() 使用同一个 GridCellErrorState<T>[] 数据源。
逐单元格编辑策略
列的 editor 和 key 仍然固定;需要让同一列在不同行具有不同权限时,使用 resolveCellEditPolicy,不要动态切换编辑器或字段绑定。
import { RenderDataGrid, type GridColumnDef } from 'ds-ui' interface OrderRow { itemCode: string dose: number approved: boolean orderType: 'drug' | 'service'} const columns: GridColumnDef<OrderRow>[] = [ { key: 'itemCode', title: '医嘱项目', type: 'text' }, { key: 'dose', title: '剂量', type: 'number' },]const rows: OrderRow[] = [] const grid = new RenderDataGrid<OrderRow>({ columns, rows, editable: true, resolveCellEditPolicy: ({ row, column }) => { if (row.approved) { return { state: 'readonly', reason: '医嘱已审核,不能再修改', } } if (column.key === 'dose' && row.orderType !== 'drug') { return { state: 'disabled', reason: '非药品医嘱不使用剂量', } } return { state: 'inherit' } },})
GridCellContext<T> 包含 row、可视 rowIndex、column、可视 columnIndex 和当前 value。GridCellEditPolicy 字段:
| 字段 | 类型 | 默认语义 |
|---|---|---|
state |
'inherit' | 'editable' | 'readonly' | 'disabled' |
inherit,继续使用 Grid 与列的编辑能力。 |
tabStop |
boolean |
editable 和显式 readonly 为 true;disabled 为 false。继承自 column.editable:false 或无有效 editor 的 readonly 列保持原有跳过行为。 |
reason |
string |
无;readonly/disabled 单元格 hover 时作为原因提示。 |
readonly保持正常阅读、焦点、选择和复制能力,但不会启动编辑器。disabled使用弱化视觉,默认从 Tab 路径跳过;显式设置tabStop:true可让它参与导航。- 未配置 resolver 时,
editable:false和没有有效 editor 的列继续从默认 Tab 编辑路径跳过;需要让这类列参与导航时,显式返回state:'readonly', tabStop:true。 - 策略覆盖鼠标、Enter/F2/Space、checkbox、弹出编辑器、粘贴和编辑中的提交;策略运行时变化为不可编辑时,当前编辑会取消而不写回。
- Grid 的
disabled、readonly、editable:false和列的editable:false是最终边界,回调不能把这些边界重新提升为 editable。 setCellValue()是程序化数据 API,不受逐单元格用户编辑策略阻断,仍会执行标准化和校验。
Lookup 感知当前单元格
Grid 列的 lookup.queryProcessor 除了查询选项,还会收到 context.cell。可用它根据当前医嘱行过滤候选项,而不需要为每一行创建不同编辑器:
import type { GridLookupQueryProcessor } from 'ds-ui' interface OrderRow { orderType: 'drug' | 'service' itemCode: string} interface OrderOption { code: string name: string orderType: OrderRow['orderType']} const queryProcessor: GridLookupQueryProcessor<OrderOption, OrderRow> = context => ({ rows: context.rows.filter(option => option.orderType === context.cell.row.orderType && String(option.name).includes(context.query) ),})
cell 在 popup 打开和每次搜索时均指向外层 Grid 单元格;它不是下拉候选行。列声明为 GridColumnDef<Row> 时,内联 queryProcessor 的 context.cell.row 会沿用该 Row 类型;单独复用处理器时可显式声明 GridLookupQueryProcessor<Option, Row>。
排序、过滤、分组和汇总
排序
GridSortDescriptor:
| 字段 | 类型 | 说明 |
|---|---|---|
key |
string |
列 key。 |
order |
'asc' | 'desc' |
排序方向。 |
sortState 是兼容单列排序状态,sort 是当前多列排序描述。业务优先使用 sort。
过滤
GridFilterRule:
| 字段 | 类型 | 说明 |
|---|---|---|
key |
string |
列 key。 |
operator |
GridFilterOperator |
过滤操作符。 |
value |
unknown |
起始值或单值。 |
valueTo |
unknown |
between 的结束值。 |
values |
unknown[] |
in、notIn 的值集合。空值使用 null。 |
GridFilterOperator 支持:
containsequalsstartsWithendsWithgtgteltltebetweenemptynotEmptyinnotIn
默认交互采用表头下拉筛选:将列设置为 filterable:true 后,表头右侧显示下拉图标。点击图标或在当前列按 Alt+ArrowDown 打开弹窗。
- “值筛选”列出当前列的唯一值、搜索和全选状态;选项保留原始数据值,显示文本沿用列编辑器的 label 解析。候选项计数不一致时显示计数,全部一致时自动隐藏低信息量的计数列。
- 数组和普通对象等复杂候选值按稳定的结构语义去重和匹配,不受对象属性声明顺序影响;循环引用等不可序列化值退回同一对象实例语义。
- “条件筛选”提供文本、数值、日期等列适用的操作符。
- 弹窗中的修改是草稿,只有“确定”或在输入区按
Enter才提交;“取消”、Escape和点击外部均放弃草稿。 Tab/Shift+Tab在清除动作、筛选页签、输入区、值列表、条件操作符和底部按钮之间循环;页签和操作符支持方向键,Enter/Space激活当前动作。- 唯一值默认最多收集 10,000 项;超过限制时搜索仅覆盖已加载项。此时从默认全选状态取消值会生成
notIn规则,未展示的值仍保持包含。 - 已生效的列显示筛选图标,弹窗打开时表头入口保持选中反馈。
- 筛选弹窗的间距、控件高度、列表行高、按钮尺寸和视口边距跟随主题密度,并复用 popup、输入框、复选框与滚动条的明暗主题状态样式。
- 筛选弹窗使用独立于列宽的首选宽度和最大宽度;宽列不会把弹窗横向拉伸,弹窗右侧与表头筛选入口保持对齐。
- 值筛选会按初始候选数量收缩高度,超过 6 个可见行后再启用滚动;搜索过程中高度保持稳定。条件筛选使用独立的紧凑高度,切换操作符时不会上下抖动。
- 弹窗优先在表头下方打开;下方能容纳基本操作区时会在下方压缩列表高度,否则紧贴表头上方打开,并按该方向的可用空间限制高度。
readonly:true只禁止数据修改,仍允许排序和筛选等数据视图操作;disabled:true会关闭并阻止筛选弹窗交互。
过滤仍保留两套数据入口:
filters:表头弹窗使用的结构化规则,也适合业务持久化。columnFilters:可选过滤行的文本值,适合需要始终可见的简单输入式过滤。通过filterRowVisible:true显式启用;不建议作为默认视觉方案。
快速过滤
quickFilter 会在数据模型中执行全局文本匹配。大数据场景中,不要在每次输入时同步构造新 rows,应通过防抖后设置 grid.quickFilter 或 grid.setQuickFilter()。
分组
GridGroupDef<T>:
| 字段 | 类型 | 说明 |
|---|---|---|
key |
keyof T & string |
分组字段。 |
order |
'asc' | 'desc' |
当前分组层级的排序方向。 |
分组列头使用 G1、G2 等徽标明确标识分组层级;该徽标不是排序优先级或筛选数量。分组行不是源数据行,事件和选择只会把数据行转换为业务行。
汇总
GridSummaryDef<T>:
| 字段 | 类型 | 说明 |
|---|---|---|
key |
keyof T & string |
汇总字段。 |
aggregate |
'sum' | 'avg' | 'min' | 'max' | 'count' |
汇总方式。 |
label |
string |
页脚标签。 |
formatter |
(value, rows, def) => string |
自定义显示文本。 |
可读写属性
| 属性 | 类型 | 说明 |
|---|---|---|
columns |
GridColumnDef<T>[] |
获取或替换全部列。替换前取消活动编辑,随后重置列宽并重新布局。 |
visibleColumns |
GridColumnDef<T>[] |
只读。按左固定、普通、右固定排序后的可见列。 |
rows |
T[] |
获取或替换源数据行。 |
dataState |
GridDataState |
数据状态。 |
stateMessage |
string |
状态提示文本。 |
selectionMode |
GridSelectionMode |
选择模式。 |
cellTextOverflow |
GridCellTextOverflow |
全局单元格文本溢出策略。 |
footerHeight |
number |
页脚高度。 |
filterRowVisible |
boolean |
是否显示过滤行。 |
filterRowHeight |
number |
过滤行高度。 |
groupBy |
GridGroupDef<T>[] |
当前分组配置。 |
disabled |
boolean |
整体禁用状态。切换为 true 会取消编辑、拖拽、popup、hover 和焦点。 |
readonly |
boolean |
只读状态。切换为 true 会取消当前编辑,但保留选择、复制和数据视图操作。 |
rowHeight |
number |
行高。 |
headerHeight |
number |
表头高度。 |
sortState |
GridSortState |
单列排序状态。 |
sort |
GridSortDescriptor[] |
多列排序状态。 |
filters |
GridFilterRule[] |
结构化过滤规则。 |
quickFilter |
string |
快速过滤文本。 |
summary |
GridSummaryDef<T>[] |
汇总配置。 |
editingCell |
{ row; key; column; text } | null |
只读。当前正在编辑的单元格。 |
getCellDisplayText |
函数或 undefined |
自定义单元格文本。 |
getGroupDisplayText |
函数或 undefined |
自定义分组文本。 |
resolveRowStyle |
函数或 undefined |
自定义行样式。 |
resolveCellStyle |
函数或 undefined |
自定义单元格样式。 |
resolveCellEditPolicy |
函数或 undefined |
按单元格解析编辑、只读、禁用、Tab 和原因提示。 |
validateCell |
函数或 undefined |
单元格校验函数。设置新函数会清理旧错误。 |
validateRow |
函数或 undefined |
行字段关联校验函数。设置新函数会清理旧错误。 |
width / height |
number | undefined |
期望尺寸。赋值后请求 layout。 |
minWidth / maxWidth |
number | undefined |
水平方向尺寸边界。赋值后请求 layout。 |
minHeight / maxHeight |
number | undefined |
垂直方向尺寸边界。赋值后请求 layout。 |
margin |
EdgeInsets |
组件外部留白。赋值后请求 layout。 |
horizontalAlignment / verticalAlignment |
BoxAlignment | undefined |
组件在父布局槽位中的对齐方式。 |
isFocused |
boolean |
只读。当前表格是否持有焦点。 |
disabled、readonly、editable、resizableColumns、autoFitColumns、rangeSelectionAutoScroll、sortable 可以在运行时直接修改。setter 会同步清理不再合法的临时状态:例如关闭编辑会取消当前编辑,关闭列宽调整会取消 resize,关闭排序会清空当前排序,禁用组件会关闭自身 popup 并释放焦点。
运行时设置 rowHeight 或 headerHeight 会转为显式尺寸,并触发布局、滚动范围和编辑器几何同步;后续主题切换不会覆盖显式值。
替换 grid.rows 表示重新绑定数据源。GridView 会结束当前编辑并关闭自身 popup;未配置 rowKey 时会清空选择、焦点、悬停和校验错误。配置 rowKey 时,选择和校验错误会按行 id 尝试恢复,但编辑状态仍会结束。
方法
编辑
| 方法 | 返回值 | 说明 |
|---|---|---|
beginEdit(row, key) |
boolean |
开始编辑,并按 nearest 将目标可视行纵向滚入视口。row 可传可视行索引或行对象;key 可传可视列索引或列 key。 |
commitEdit() |
boolean |
提交当前编辑。校验失败时返回 false。 |
cancelEdit() |
void |
取消当前编辑。 |
setCellValue(row, key, value) |
boolean |
通过 API 设置单元格值。row 可传源行对象或可视行索引。 |
validate() |
GridValidationResult<T> |
验证活动编辑器以及全部源数据行、列,并返回完整错误集合。 |
focusFirstError() |
boolean |
定位第一个可见错误单元格;没有可定位错误时返回 false。 |
getCellErrors() |
GridCellErrorState<T>[] |
获取单元格错误。 |
clearCellErrors() |
void |
清除所有单元格错误。 |
clearCellError(row, key) |
boolean |
清除指定源数据行、指定字段的错误;其他字段错误保持不变。 |
beginEdit() 只定位当前排序、过滤和分组投影中的可视数据行。目标行被过滤排除、目标列被隐藏或当前编辑策略不允许编辑时返回 false,不会自动清除筛选条件。自动定位只保证纵向行可见,不改变横向滚动位置。
过滤和搜索
| 方法 | 返回值 | 说明 |
|---|---|---|
getFilterValue(key) |
string |
获取过滤行文本。 |
setFilterValue(key, value) |
void |
设置过滤行文本。 |
getFilters() |
GridFilterRule[] |
获取结构化过滤规则。 |
setFilters(filters) |
void |
设置结构化过滤规则。 |
getQuickFilter() |
string |
获取快速过滤文本。 |
setQuickFilter(value) |
void |
设置快速过滤文本。 |
clearAllFilters() |
void |
清除过滤行、结构化过滤和快速过滤。 |
clearColumnFilter(key) |
void |
清除某列过滤。 |
getColumnFilters() |
GridColumnFilterState[] |
获取过滤行状态。 |
setColumnFilters(filters) |
void |
设置过滤行状态。 |
分组
| 方法 | 返回值 | 说明 |
|---|---|---|
expandAllGroups() |
void |
展开全部分组。 |
collapseAllGroups() |
void |
折叠全部分组。 |
选择和定位
| 方法 | 返回值 | 说明 |
|---|---|---|
getVisibleRows() |
readonly T[] |
获取当前排序、过滤、分组后的可视数据行。 |
focusRow(row, options?) |
boolean |
聚焦某行。options.select 默认 true;options.scroll 控制是否滚动到行。 |
setSelectedRows(rows) |
void |
设置选中行。元素可为行对象或可视行索引。 |
setSelectedRowIds(rowIds) |
void |
按行 id 设置选中行。需要配置 rowKey。 |
getSelectionState() |
GridSelectionState<T> |
获取完整选择状态。 |
getSelectedRows() |
readonly T[] |
获取选中行。 |
getSelectedRow() |
T | null |
获取第一条选中行。 |
getSelectedRowIds() |
GridRowId[] |
获取选中行 id。 |
getCurrentCell() |
GridSelectionCell<T> | null |
获取当前单元格。 |
getCurrentRow() |
T | null |
获取当前行。 |
getCurrentColumn() |
GridColumnDef<T> | null |
获取当前列。 |
getCurrentKey() |
keyof T & string | null |
获取当前列 key。 |
getFocusedCell() |
GridSelectionCell<T> | null |
获取焦点单元格。 |
getFocusedRow() |
T | null |
获取焦点行。 |
getFocusedColumn() |
GridColumnDef<T> | null |
获取焦点列。 |
getFocusedKey() |
keyof T & string | null |
获取焦点列 key。 |
clearSelection() |
void |
清除选择。 |
selectCell(row, key, options?) |
boolean |
选择单元格。 |
selectRange(range, options?) |
boolean |
选择范围。 |
GridSelectionOptions:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
scroll |
boolean |
true |
程序化选择后是否滚动到目标单元格或范围。 |
数据行
| 方法 | 返回值 | 说明 |
|---|---|---|
addRows(rows, sourceIndex?) |
boolean |
添加行。sourceIndex 是源数据索引,不是可视索引。 |
addRowsAtSourceIndex(rows, sourceIndex) |
boolean |
按源数据索引插入。 |
insertRowsBefore(referenceRow, rows) |
boolean |
在指定业务行前插入。 |
insertRowsAfter(referenceRow, rows) |
boolean |
在指定业务行后插入。 |
removeRows(rows) |
boolean |
删除行。元素可为行对象或源数据索引。 |
refreshRow(row) |
boolean |
刷新指定行显示。 |
refreshData() |
void |
刷新全部数据呈现。 |
refreshLookup(columnKey?) |
boolean |
重建指定 Lookup 列或全部 Lookup 列的值索引并刷新呈现;没有匹配列时返回 false。同一候选数组保持相同长度但原地替换内容后应调用此方法。 |
列状态
| 方法 | 返回值 | 说明 |
|---|---|---|
moveColumn(fromIndex, toIndex) |
boolean |
移动可见非固定列。移动前提交活动编辑;校验失败或固定列不能移动时返回 false。 |
openColumnMenu(column, position?) |
boolean |
打开列菜单。column 可传列 key 或可见列索引。 |
getViewPreset() |
GridViewPreset |
导出列状态、排序、过滤和快速过滤。 |
applyViewPreset(preset) |
void |
恢复视图预设。 |
resetColumnState() |
void |
恢复初始列状态。 |
autoFitColumn(column) |
boolean |
自动适配单列宽度。 |
autoFitAllColumns() |
void |
自动适配所有可见列宽。 |
resetColumnWidths() |
void |
恢复初始列宽。 |
getColumnState() |
GridColumnState[] |
获取列宽、隐藏、固定和宽度模式。 |
setColumnState(state) |
void |
取消活动编辑,然后设置列状态和列顺序。 |
焦点、复制和调试
| 方法 | 返回值 | 说明 |
|---|---|---|
focusIn() |
void |
通知组件获得焦点。通常由焦点系统调用。 |
focusOut() |
void |
通知组件失去焦点。通常由焦点系统调用。 |
getCopyText() |
string | null |
获取当前选择可复制文本。 |
debugState() |
GridDebugState |
获取滚动、选择、排序、过滤、列、错误等调试状态。 |
dispose() |
void |
释放焦点注册、编辑器、popup 控制器、指针控制器和滚动状态。 |
事件与回调
| 回调 | 触发时机 | 参数说明 |
|---|---|---|
onCellChange(row, key, value) |
单元格提交且校验通过后 | row 是源行对象;key 是列 key;value 是标准化后的值。 |
onRowClick(row, event) |
用户点击数据行 | event 包含 rowId、key、column、输入来源和组合键状态。 |
onRowActivate(row, event) |
用户激活数据行 | 常见来源是双击或键盘确认。 |
onSelectionChange(event) |
行、单元格或范围选择变化 | event.state 是完整选择状态;selectedRow 是第一条选中行。 |
onCurrentCellChange(cell) |
当前单元格变化 | cell 为 null 表示当前单元格被清空。 |
onFocusedCellChange(cell) |
焦点单元格变化 | 焦点单元格可不同于当前选择。 |
onScrollChange(scrollY) |
纵向滚动位置变化 | 只回传纵向滚动偏移。 |
GridRowEvent<T> 字段:
| 字段 | 说明 |
|---|---|
rowId |
行 id。未配置 rowKey 时可能是 null。 |
key |
触发事件的列 key,无法解析列时为 null。 |
column |
触发事件的列定义。 |
input |
'pointer' | 'keyboard' | 'api'。 |
shiftKey / ctrlKey / metaKey / altKey |
组合键状态。 |
选择模型
selectionMode 支持:
row:行选择。适合查询列表和主从页面。cell:单元格选择。适合轻量编辑表。range:范围选择。适合复制、批量编辑和表格型录入。
GridSelectionState<T> 字段:
| 字段 | 说明 |
|---|---|
mode |
当前选择模式。 |
selectedRows |
选中的业务行对象。 |
selectedRowIds |
选中的行 id。 |
currentCell |
当前单元格。 |
selectedRanges |
选区范围。 |
focusedRow |
焦点行。 |
focusedKey |
焦点列 key。 |
focusedColumn |
焦点列定义。 |
键盘、鼠标和复制行为
- 鼠标点击数据行会更新焦点、当前行和选择状态。
- 鼠标双击数据行会触发
onRowActivate;单击只触发onRowClick。表格不可编辑时,按 Enter 也会激活当前行。 - 拖拽列边界可调整列宽,前提是
resizableColumns=true。指针进入可调整边界时显示col-resize光标和弱预览线;按下拖动后使用更强的贯穿式指示线,离开、取消、禁用或释放能力时会清理反馈。 - 双击列边界可自动适配列宽,前提是
autoFitColumns=true。 - 表头右键或列菜单入口可打开列菜单。
- 鼠标滚轮滚动可视行,不会重建所有行对象。
- 选择文本溢出的单元格时,hover 会显示完整文本 tooltip。
getCopyText()返回当前选择对应的文本,供框架剪贴板逻辑使用。- 编辑状态下键盘优先交给内置编辑器;非编辑状态下键盘用于选择和导航。
- 数字编辑状态下,上下方向键执行
step步进;结束编辑后恢复为上下行导航。 - Popup 打开时,键盘优先交给 PopupManager 处理。
状态表现
dataState 为 ready 时显示数据。其他状态:
loading:显示加载提示。empty:显示空数据提示。即使dataState='ready',可视行数为 0 时也会表现为空。error:显示错误提示。
状态文本由 stateMessage 控制。非 ready 且鼠标在主体区域时,主体交互会被忽略,避免在无数据状态下选中旧行。
整体状态:
disabled=true:使用弱化遮罩表达不可操作状态,不显示 hover/focus,且不响应滚动、选择、复制、菜单或编辑。readonly=true:保持正常可读视觉和选择反馈;允许复制、滚动、排序、过滤和分组展开,但不允许修改业务数据。editable=false:只关闭单元格与结构编辑,不等价于整体禁用。- 逐单元格
disabled会弱化该单元格,readonly保持普通可读外观;两者都允许鼠标选择,原因可通过 tooltip 查看。
样式和显示文本
GridRowStyleArgs<T> 包含 row、rowId、theme、backgroundColor、selected、hovered、focused 和 editing。其中 backgroundColor 是进入业务回调前已经解析出的当前状态背景;GridCellStyleArgs<T> 会把它更新为当前单元格实际使用的基础背景,并额外提供 value、column 和 error。
自定义列的 renderColor(value, row, context) 使用同一个 GridCellStyleArgs<T> 上下文。旧的两参数回调仍兼容;需要跨明暗主题和选中态保持可读时,应根据 context.theme 与 context.backgroundColor 解析颜色。
resolveRowStyle(args) 可返回:
| 字段 | 说明 |
|---|---|
backgroundColor |
行背景色。 |
textColor |
行文本色。 |
borderColor |
行边框色。 |
fontSize |
行字体大小。 |
fontFamily |
行字体。 |
resolveCellStyle(args) 额外支持:
| 字段 | 说明 |
|---|---|
align |
单元格对齐方式。 |
getCellDisplayText(args) 用于控制显示文本,不改变源数据值。典型场景:
- 枚举值显示成中文。
- 金额格式化。
- 日期格式化。
- 根据错误状态显示特殊文本。
持久化视图状态
使用 getViewPreset() 和 applyViewPreset() 可以保存和恢复:
- 列宽。
- 列顺序。
- 列隐藏。
- 固定列位置。
- 列宽模式。
- 排序。
- 结构化过滤。
- 过滤行文本。
- 快速过滤。
示例:
import type { RenderDataGrid } from 'ds-ui' declare const grid: RenderDataGrid<any> const preset = grid.getViewPreset()localStorage.setItem('patient-grid', JSON.stringify(preset)) const saved = localStorage.getItem('patient-grid')if (saved) { grid.applyViewPreset(JSON.parse(saved))}
性能原则
rows应尽量保持业务对象稳定。只变更某一行时优先修改对象后调用refreshRow(row)。- 每个 GridView 实例会按 Lookup 列维护独立的
valueKey → row索引。绘制、悬停、复制、筛选和分组只查询索引,不会在交互热路径反复扫描完整候选数组。 - 替换 Lookup 的
rows引用、改变候选数量或替换列配置时索引会自动重建。同一数组保持相同长度但原地修改候选键时,调用refreshLookup(columnKey)明确刷新索引。 - Lookup 索引只负责已选值的显示解析;
queryProcessor仍决定 popup 中本次查询的候选结果、顺序和数量。 - 大数据下不要每次 hover、输入或滚动都重建
columns和rows数组。 autoFitColumns和widthMode:'autoContent'会测量文本。组件内部有采样限制,但仍不应在高频路径反复触发。getCellDisplayText、resolveRowStyle、resolveCellStyle、resolveCellEditPolicy会在绘制可视单元格时调用,逻辑必须轻量,不要访问网络或做大对象遍历。- 过滤和排序在数据模型层执行。几十万行场景应在业务层考虑分页、服务端查询或防抖。
- 固定列会增加绘制分区,但仍只绘制可视行。
当前限制
- 排序、过滤、分组和汇总均在客户端数据模型中执行。几十万行或远程数据源应由业务层提供分页、服务端查询和防抖,不应一次传入全部数据。
- 虚拟化使用统一
rowHeight,当前不支持按行动态高度、合并单元格或跨行布局。 GridColumnCustom主要用于自定义显示;需要完整自定义交互或层级行时,应分别使用显式 editor 或 TreeGrid。- 只读状态面向交互约束;业务代码仍可通过
setCellValue()、替换rows等公开 API 主动更新数据。
常见组合
- 查询表单 + GridView:查询条件放在 TextField、Dropdown、DatePicker 等组件中,查询后替换
rows。 - GridView + 命令按钮:使用 CommandButton 或 CommandToolbar 控制新增、删除、导出、刷新。
- GridView + 弹窗编辑:行点击后打开 Modal、Drawer 或 Popup 编辑详细信息。
- GridView + TreeGrid:普通列表用 GridView,有层级关系时用 TreeGrid。
相关组件
- TreeGrid 树表:层级数据表格。
- Table 静态表格:少量静态数据展示。
- EntryGrid 键值表格:表单型键值布局。
- ListView 列表:单列列表和选择。
- LookupEdit 查询选择:独立查询选择组件。
- DropTreeGridEdit 树表下拉:树表弹出选择。
- CommandToolbar 命令工具栏:表格上方操作区。
- Runtime Diagnostics:调试绘制、布局和事件。