@taocompany/magic-grid
v0.12.0
Published
A high-performance virtual table component library for Vue 3
Maintainers
Readme
Magic Grid
面向 Vue 3 的高性能虚拟表格组件库。采用命令式渲染 + 行 DOM 池 + 双轴虚拟化,可稳定承载百万级行数据;API 设计对标 AG Grid 社区版,覆盖排序、筛选、编辑、行分组、树形表格、框选、剪贴板等完整表格能力。
目录
- 概述
- 架构与设计
- 快速开始
- 行移动
- 数据与性能最佳实践
- 树形表格
- 默认配置
- Props
- Options 类型参考
- 筛选模型参考
- Events
- Expose
- Slots
- 单元格编辑
- 数据校验
- 键盘导航与快捷键
- 辅助组件
- 包入口与导出
- TypeScript 集成
- 类型与校验子路径
概述
特性
| 类别 | 能力 |
|------|------|
| 性能 | 行/列双轴虚拟化、DOM 池复用、RAF 帧预算分片、Cell Renderer 滚动调度(idle flush · 按行合并 · placeholder-then-vue)、增量数据管线 |
| 数据 | 排序、列筛选、Quick Filter、事务增量更新(applyTransaction)、行 CRUD、行移动(moveRow / moveRows) |
| 交互 | 单元格/行编辑(内置 text/number/checkbox/switch · overlay/inline)、校验、行选择、索引列定位、框选与剪贴板 |
| 布局 | 固定列、列拖拽/调整宽度、列有效性与显隐(available / hidden)、合并单元格、动态行高、主从展开行 |
| 结构 | 行分组、树形表格(含懒加载)、表尾汇总 |
| 体验 | 溢出 Tooltip、单元格批注、空态 Overlay、暗色主题、底部状态栏 |
| 扩展 | 列设置面板、内置编辑器(text/number/checkbox/switch)、Vue 第三方编辑器 Composable、inline 常驻编辑器、async-validator 校验 |
当前版本:0.7.5(@taocompany/magic-grid)。
上手路径:安装 → 快速开始 → 按需查阅 行移动、树形表格 等专题,以及下文 Props / Events / GridApi 索引。
环境要求
- Node.js >= 20.19
- Vue ^3.5.0
- async-validator ^4.2.0(校验功能 peer dependency)
安装
pnpm add @taocompany/magic-grid async-validator引入样式
样式不会随 JS 自动注入。须先 token、后 style(全局引入一次):
import '@taocompany/magic-grid/tokens.css'
import '@taocompany/magic-grid/style.css'ColumnSettingsButton / ColumnSettingsPanel 与 MagicGrid 共用上述两份 CSS。按钮若在 MagicGrid 容器外,同样必须引入;列设置相关 token 在
.mg-column-settings-button/.mg-column-settings-portal上也会注入,脱离.magic-grid可正常显示。主题拆分见 docs/48-theme-tokens-style-split.md;平台自定义 token 与可视化导出方案见 docs/49-theme-studio.md(在tokens.css之后加载mg-theme-overrides.css)。
架构与设计
Magic Grid 采用 命令式渲染内核 + Vue 薄封装 的分层架构,对标 AG Grid 社区版 API 语义,渲染路径针对百万级行数据做了专门优化。
分层结构
| 层级 | 职责 | 关键模块 |
|------|------|----------|
| Vue 层 | Props / Events / Slots 绑定、主题 CSS 变量、辅助 UI | MagicGrid.vue、ColumnSettings、StatusBar |
| Grid API | 命令式数据、列、编辑、选择、框选 | GridApi |
| 渲染引擎 | 双轴虚拟化、行 DOM 池、增量 cell 刷新 | rowRenderer、rowPool |
| 数据管线 | 排序 / 筛选 / 分组 / 树形 / 映射 | pipeline stages |
| 交互层 | 焦点、框选、编辑、拖拽、剪贴板、批注 | gridInteraction |
渲染模型
- 行虚拟化:仅渲染视口 +
rowBuffer缓冲行;行 DOM 在行池内按rowKey复用,滚动时更新内容与位置。 - 列布局:左固定 / 中心 / 右固定三 lane;中心 lane 随横滚分配列宽。
- 增量更新:
applyTransaction、setData走 RowNode 增量管线;beginUpdate/endUpdate可合并多次刷新。 - 帧预算:大批量 DOM 写入分片到
requestAnimationFrame(默认 60ms/帧);cellRenderer/#cell-xxx插槽走 f1 低优先级队列,可通过 Cell Renderer 滚动渲染 调优;测试场景可调用flushFrames()同步 flush。
数据管线顺序
| 模式 | Stage 顺序 |
|------|------------|
| 扁平表格 | sort → filter → map |
| 行分组 | group → filter → sort → aggregate → map |
| 树形表格 | tree → filter → sort → map |
详见 树形表格 专章。
summaryScope: 'displayed'、状态栏行数、框选聚合均基于 rowsToDisplay;summaryScope: 'all' 对 sourceRows 全量汇总(忽略 filter)。
快速开始
<script setup lang="ts">
import { ref } from 'vue'
import { MagicGrid } from '@taocompany/magic-grid'
import type { ColumnDef, MagicGridExpose, RowData } from '@taocompany/magic-grid/types/core'
import '@taocompany/magic-grid/tokens.css'
import '@taocompany/magic-grid/style.css'
const gridRef = ref<MagicGridExpose>()
const columns: ColumnDef[] = [
{ prop: 'name', label: '姓名', width: 120 },
{ prop: 'age', label: '年龄', width: 80 },
{ prop: 'city', label: '城市', flex: 1 },
]
const data: RowData[] = [
{ id: 1, name: '张三', age: 28, city: '上海' },
{ id: 2, name: '李四', age: 32, city: '北京' },
]
function onSelectionChanged(event: { selectedRowIds: readonly (string | number)[] }) {
console.log('选中行:', event.selectedRowIds)
}
</script>
<template>
<MagicGrid
ref="gridRef"
:columns="columns"
:data="data"
row-key="id"
height="400"
row-selection="multiple"
sortable
filterable
stripe
@selection-changed="onSelectionChanged"
/>
</template>提示:
data应为普通对象数组,避免对行数据使用reactive()深代理。
上例通过 Grid 级 sortable / filterable 开启全列默认可排序、可筛选;个别列可用 sortable: false / filterable: false 关闭。详见 Grid 级默认与列级覆盖。
替代写法(逐列显式配置):
const columns: ColumnDef[] = [
{ prop: 'name', label: '姓名', width: 120, sortable: true },
{ prop: 'age', label: '年龄', width: 80, sortable: true },
{ prop: 'city', label: '城市', flex: 1, filterable: true },
]<MagicGrid :columns="columns" :data="data" row-key="id" height="400" />行移动
MagicGrid 支持编程式 API与索引列 UI 拖拽两种方式调整行序。无论哪种方式,最终都修改 source 数组(即 api.getData() / ref.getData() 返回的顺序),表格按当前 sort / filter / 分组 / 树形规则重新计算可见顺序(rowsToDisplay)。
核心概念:source 与 display
| 概念 | 含义 | 消费端如何观察 |
|------|------|----------------|
| source 顺序 | 业务数据在内存中的存储顺序 | getData() 下标 · RowNode.sourceIndex · snapshot.sourceIndex · getRowIndex(id) 默认 |
| display 顺序 | sort/filter/分组后屏幕可见顺序 | RowNode.rowIndex · snapshot.rowIndex · getRowIndex(id, { type: 'display' }) |
| rowsToDisplay | 内核可见行列表(含 groupHeader 等) | 不直接暴露;分组表 indexMode:'display' 的 toIndex 含 header/footer |
分组表 source 序:开启 rowGrouping 后,setData / 事务 / 分组键配置变更触发的全量 refresh 前,source 会按分组键 collation 归一化(组间 groupComparator,组内稳定相对顺序)。因此稳态下 getData() 已是「组块 + 组内序」,不是长期交错的 raw 数组。展开/折叠(map-only refresh)不会重排 source。
组内换序只改变 source 中同组 leaf 的相对位置,不会把行移到另一组(跨组须改分组字段值)。
行移动前置配置
| Prop | 典型值 | 说明 |
|------|--------|------|
| show-index-column | true | 显示索引列;drag handle 与 index focus 的前提 |
| index-column.showRowDragHandle | true | 索引列左侧拖拽把柄 |
| index-column.focusMode | 'multiple' | 索引列多选 focus,可整块移动(不读取 checkbox 行选) |
| row-drag-managed | true(默认) | drop 后自动写回 source 并触发 row-moved;false 时自行监听 row-drag-end 改序 |
<MagicGrid
show-index-column
:index-column="{ showRowDragHandle: true, focusMode: 'multiple' }"
row-drag-managed
@row-moved="onRowMoved"
/>平铺表:UI 拖拽与 API
UI 拖拽:在索引列 focus 一行或多行 → 拖左侧 handle → 松手后 source 顺序更新。
编程式 API:
const api = gridRef.value?.api
// 移动单行:将 id=3 的行移到 source 下标 0
api?.moveRow(3, 0)
// 批量移动:将 id 2、3、4 作为一块移到 source 下标 0,块内相对顺序不变
api?.moveRows({ rowIds: [2, 3, 4], toIndex: 0 })
// 结合索引列 focus(默认 mode: 'all',含临时行 internalRowId)
const rowIds = api?.getIndexFocusedRowIds() ?? []
if (rowIds.length > 0) {
api.moveRows({ rowIds, toIndex: 0, indexMode: 'display' })
}moveRows 不读取 checkbox 选区(rowSelection)。若需按 checkbox 选中移动,请 generateSelectedRowIds(getSelectedRows())。
勿将 indexFocusChanged 的 focusedRowIds(临时行为 null)直接传给 moveRows;请用 getIndexFocusedRowIds() 或 generateFocusedRowIds(focusedRows)。
返回值 RowMoveResult:{ moved: true, fromIndex, toIndex, moves? } 或 { moved: false, reason }。失败时 不修改 source,不 emit row-moved。
步进换序 moveUp / moveDown
一行代码在相邻行之间步进换序,返回移动后的 RowSnapshot;边界或行不存在时 null。
| 表形态 | 步进范围 | 内部坐标 |
|--------|----------|----------|
| 平铺表 | 全局 source 邻居 | indexMode: 'source' |
| 分组表 | 同 leafGroupPathKey 组内 leaf | indexMode: 'source'(collation 后的 source 子序列) |
| 树形表 | 同父兄弟 | indexMode: 'display'(可见兄弟邻居) |
import { generateRowId } from '@taocompany/magic-grid'
const row = api.getIndexFocusedRows()[0]
if (!row) return
const snapshot = api.moveUp(generateRowId(row)) // 上移一位
// api.moveDown(generateRowId(row)) // 下移一位
// snapshot?.sourceIndex · snapshot?.rowIndex // 移动后的下标Playground:/docs/row-move-step(平铺)· /docs/row-move-step-grouped(分组)。
分组表:组内换序
开启 rowGrouping 后,行移动**限定在同一分组下的数据行(leaf)**内,不可跨组、不能通过 drag/API 改分组字段。
<MagicGrid
row-grouping
show-group-header
show-index-column
:index-column="{ showRowDragHandle: true, focusMode: 'multiple' }"
row-drag-managed
:columns="[
{ prop: 'department', rowGroup: true, rowGroupIndex: 0, label: '部门', width: 120 },
{ prop: 'name', label: '姓名', width: 120 },
]"
/>推荐:组内步进用上一节的 moveUp / moveDown(无需手算邻居下标)。
高级:moveRow / moveRows + indexMode: 'display'(与 UI drag 同语义):
const rowIds = api.getIndexFocusedRowIds()
if (rowIds.length === 0) return
const rowId = rowIds[0]!
const department = api.getData().find((r) => String(r.id) === String(rowId))?.department
const groupLeaves = api.getData().filter((r) => r.department === department)
const pos = groupLeaves.findIndex((r) => String(r.id) === String(rowId))
const neighbor = groupLeaves[pos - 1] // 上移时
if (!neighbor) return
const toIndex = api.getRowIndex(neighbor.id, { type: 'display' })
if (toIndex == null) return
api.moveRow(rowId, toIndex, 'display')跨组时返回 { moved: false, reason: 'cannot move rows across groups' }。
完整示例:Playground /docs/row-move-grouped。
indexMode 说明
| 值 | toIndex 含义 | 适用场景 |
|----|----------------|----------|
| 'source'(默认) | source 数组下标(分组表 = collation 归一化后的序) | 平铺表、分组表组内换序 |
| 'display' | 当前可见行下标(含 groupHeader 等) | 按肉眼可见顺序移动;分组表 moveRow 高级用法 |
sort 或 filter 激活时:moveRow / moveRows / moveUp / moveDown 与 managed 拖拽 handle 全部不可用;须先 clearAllFilters() / setSortModel([])。
约束与常见失败原因
| 场景 | 行为 |
|------|------|
| sort 或 filter 激活 | managed 拖拽 handle 隐藏;moveRow / moveRows / moveUp / moveDown 全部拒绝 |
| 行分组 | 须同一组 leaf;不可跨组 |
| 树形 | 须同一父节点下兄弟;跨父 reorder 仅 UI hierarchy drag + asyncRowMutation.move |
常见 reason:row move is not allowed while sort or filter is active · no rows to move · selected rows must belong to the same group · cannot move rows across groups · selected rows must belong to the same tree parent
事件
| 事件 | 说明 |
|------|------|
| @row-moved / api.on('rowMoved') | 换序成功后触发;source: 'api' 或 'uiRowDrag';fromIndex / toIndex 为 source 下标 |
| @row-drag-end | rowDragManaged: false 时由业务自行改序 |
| @index-focus-changed | 索引列 focus 变化(与 checkbox 选区独立) |
moveRows 参数与返回值
MoveRowsGridApiOptions:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| rowIds | RowId[] | — | 必填。待移动行的业务 rowKey(string \| number) |
| toIndex | number | — | 必填。目标下标;含义由 indexMode 决定 |
| indexMode | 'source' \| 'display' | 'source' | 下标基准 |
| leaderRowId | RowId | source 中最早出现的行 | 块 anchor:toIndex 表示 leader 移动后的位置,其余行随块保持相对顺序 |
RowMoveResult:
| 字段 | 类型 | 说明 |
|------|------|------|
| moved | boolean | 是否发生位移 |
| fromIndex | number? | leader 变更前 source 下标 |
| toIndex | number? | leader 变更后 source 下标 |
| moves | { rowId, fromIndex, toIndex }[]? | 块内各行位移明细 |
| reason | string? | moved: false 时的失败原因 |
moveRow(rowId, toIndex, indexMode?) 为单行语法糖;moveRows 在 rowIds.length === 1 时与之等价。更多 API 索引见 GridApi、事件见 row-moved。
数据与性能最佳实践
行数据
data使用普通对象数组,不要对行数据做reactive()深代理;Grid 内部维护 RowNode,深代理会显著拖慢增量更新。rowKey必须稳定唯一(业务主键);临时新增行可省略主键,内核分配__MG_TMP__::*(不对用户暴露),落库后调用promoteRowId。- 大批量写入优先
applyTransaction或beginUpdate/endUpdate包裹多次 API 调用,避免连续setData全量替换。
列定义
- 动态列用
columnsprop 热更新即可;available: false从模型裁剪,hidden: true保留模型仅不渲染。 - flex 列与固定
width列混用时,剩余空间由 flex 权重分配;sizeColumnsToFit/autoSizeStrategy可首屏自适应。 - 需要权限裁剪时用
available,需要用户临时隐藏列时用hidden+ 列设置面板。
性能提示
- 避免在
cellRenderer/formatter/valueGetter中创建重量级对象或触发外部副作用;这些函数在滚动时会高频调用。 - 多列使用
#cell-{colId}Vue 插槽时,滚停后可能出现 renderer 列空白拖尾;见下方 Cell Renderer 滚动渲染。 - 合并单元格(
enableCellSpan)会启用style.top行定位并增加 span cache 开销,仅在确有需求时开启。 - 生产环境可通过
@scroll(ScrollEvent)监听滚动位置,通过@data-rendered(GridMetrics)订阅渲染完成时机;开发调试时可关注 DOM 行池规模与setData耗时。
Cell Renderer 滚动渲染
带 cellRenderer 或 #cell-{colId} 插槽的列在滚动时走 f1 异步队列(与 prop / formatter 列的同步 textContent 路径不同)。多 Vue 组件列场景下,可通过以下 Grid 级 prop 调优(默认均保持优化前行为,需显式开启):
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| scrollEndFlushMs | number | 0 | 滚动停止 debounce 后 flush RAF;多 Vue 列建议 100~200 |
| frameBudgetMs | number | 60 | 活跃滚动时每帧任务预算(ms) |
| scrollEndFrameBudgetMs | number | -1 | idle flush 帧预算;-1 = 一次跑完 |
| cellRendererDefer | 'always' \| 'never' \| 'sync-only' | 'always' | renderer 是否进入 f1;sync-only 仅 Vue renderer 异步 |
| deferRowDestroyOnScroll | boolean | false | 滚动 active 期间延迟行 destroy + Vue unmount |
| rendererFrameBudgetMs | number | 20 | 滚动 active 时为 f1 预留的每帧保底预算(ms);0 = 与 p1/p2 共享 |
| cellRendererPresentation | 'immediate' \| 'deferred' \| 'placeholder-then-vue' | 'deferred' | placeholder-then-vue:滚动态先显示 formattedValue,idle 后 mount Vue |
| rowBuffer | number | 10 | 行虚拟化缓冲;多 Vue 列可降至 3~5 |
列级可选 cellRendererMount: 'vue' | 'sync',配合 cellRendererDefer: 'sync-only' 精确控制哪些列走 f1。
多 slot 列业务表推荐配置(如 ProductOrder):
<MagicGrid
:row-buffer="5"
:scroll-end-flush-ms="150"
:renderer-frame-budget-ms="20"
:defer-row-destroy-on-scroll="true"
cell-renderer-presentation="placeholder-then-vue"
cell-renderer-defer="always"
...
/>placeholder-then-vue 模式下,slot 列需配置可读 prop 或 formatter,滚动态才有文字兜底。调优项见上表。
树形表格
树形表格(Tree Table)在 扁平 data 数组 上,通过 getDataPath 为每行提供 从根到当前节点的路径(string[]),内核据此构建层级并 DFS 投影 为可见的 rowsToDisplay。对标 AG Grid Tree Data 社区版语义。
与行分组互斥:
tree: true与rowGrouping: true不得同时生效。双开时控制台 dev 警告,tree优先,rowGrouping及ColumnDef.rowGroup被忽略。flat / group / tree 三选一,见 概述与核心概念。
概述与核心概念
为什么用扁平数组 + getDataPath?
Magic Grid 不支持嵌套 children 字段作为树数据源(与 AG Grid CSRM 一致)。所有行仍存放在 同一个 data 数组 中;层级关系完全由 getDataPath({ data }) => string[] 表达:
| 概念 | 说明 |
|------|------|
| dataPath | 从根到当前节点的路径段,如 ['总部', '研发部', '前端组'] |
| treeLevel | 深度,根节点 = 0,等于 dataPath.length - 1 |
| parentRowId | 父节点 rowKey;根节点为 undefined |
| rowsToDisplay | 折叠感知的 DFS 扁平投影;渲染层 只消费此数组 |
| sourceRows | 业务 flat 数组;getData() / applyTransaction 仍操作此层 |
示例路径(组织树):
| 行 id | dataPath | treeLevel | 含义 |
|-------|----------|-----------|------|
| hq | ['HQ'] | 0 | 根 |
| eng | ['HQ', '研发'] | 1 | HQ 下研发部 |
| fe | ['HQ', '研发', '前端'] | 2 | 研发部下前端组 |
路径规则(必须遵守)
- 前缀唯一确定父子:
['A','B']的父路径必须是['A'];缺父路径 → 建树 throw。 - 同一路径不得对应多行:重复路径 → 建树 throw。
- 路径段为任意字符串:可含中文、空格、特殊字符;内核用
\0拼接做内部 key。 rowKey必须稳定唯一:与 flat 表格相同;临时行内部 id 为__MG_TMP__::*,落库后promoteRowId。
数据管线(tree 模式)
启用 tree: true 后,阶段顺序为:
sourceRows(flat)
→ [tree] TreeBuildStage(getDataPath 建树)
→ [filter] 递归过滤 · 空枝剪枝
→ [sort] 同级兄弟排序(不跨层)
→ [map] DFS 扁平化(折叠跳过子树)
→ [afterMap] detail 行注入(若 masterDetail)
→ positionRows → displayRows- expand/collapse 走 map-only 快路径(
refreshModel({ stages: ['map'] })),不重跑 tree/filter/sort。 summaryScope: 'displayed'、状态栏行数、框选聚合均基于投影后的可见行。
与 rowGrouping 的区别
| 维度 | 行分组 (rowGrouping) | 树形表格 (tree) |
|------|------------------------|-------------------|
| 层级来源 | 列值 rowGroup 聚合 | getDataPath 路径 |
| 数据行 | leaf + synthetic group 行 | 全部为 user data 行 |
| 系统列 | auto group 列(__group__) | tree 列(__tree__) |
| 管线 | group → filter → sort → aggregate → map | tree → filter → sort → map |
| 互斥 | 与 tree 不得双开 | 与 rowGrouping 不得双开 |
树形表格快速上手
<script setup lang="ts">
import { ref } from 'vue'
import { MagicGrid } from '@taocompany/magic-grid'
import type { ColumnDef, GetDataPathFn, RowData } from '@taocompany/magic-grid/types/core'
import '@taocompany/magic-grid/tokens.css'
import '@taocompany/magic-grid/style.css'
interface OrgRow extends RowData {
id: string
org: string
dept?: string
team?: string
name: string
headcount: number
}
/** flat 源数据——无 children 嵌套 */
const data = ref<OrgRow[]>([
{ id: 'hq', org: 'HQ', name: '总部', headcount: 120 },
{ id: 'eng', org: 'HQ', dept: '研发', name: '研发部', headcount: 80 },
{ id: 'fe', org: 'HQ', dept: '研发', team: '前端', name: '前端组', headcount: 20 },
{ id: 'be', org: 'HQ', dept: '研发', team: '后端', name: '后端组', headcount: 25 },
{ id: 'sales', org: 'HQ', dept: '销售', name: '销售部', headcount: 30 },
])
const columns: ColumnDef[] = [
{ prop: 'name', label: '名称', width: 140, filterable: true },
{ prop: 'headcount', label: '人数', width: 88, sortable: true },
]
/** 由 org → dept → team 拼路径;也可直接读 row.pathSegments */
const getDataPath: GetDataPathFn = ({ data }) =>
[data.org, data.dept, data.team].filter(Boolean).map(String)
</script>
<template>
<MagicGrid
:data="data"
:columns="columns"
row-key="id"
height="480"
tree
:get-data-path="getDataPath"
:group-default-expanded="-1"
:row-selection="{ mode: 'multiple', groupSelectsChildren: true }"
@tree-node-opened="(e) => console.log('treeNodeOpened', e)"
/>
</template>效果:左侧自动注入 tree 系统列(缩进 + chevron + 路径末段或 name),支持折叠/展开、同级排序筛选、父子联动行选。
树形表格配置项详解
以下为树形相关 Grid 级 prop 完整说明。类型定义见 @taocompany/magic-grid/types/core 中的 TreeTableGridOptions。
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| tree | boolean | false | 总闸。true 时启用树形模式;必填 getDataPath |
| getDataPath | GetDataPathFn | — | ( { data } ) => string[],每行返回路径。tree: true 时必填,缺失则 throw |
| groupDefaultExpanded | number | -1 | 默认展开层级(tree / group 共用此 prop)。0 = 全折叠;1 = 仅展开第一层;-1 = 全部展开 |
| showTreeColumn | boolean | true | 是否注入 tree 系统列(colId __tree__) |
| autoTreeColumnDef | Partial<ColumnDef> | — | 覆盖 tree 列宽、pinned、headerName 等;对标 AG Grid autoGroupColumnDef |
| treeValueGetter | TreeValueGetterFn | — | 自定义 tree 列展示文案;缺省为 dataPath 末段 |
| treeDisplayType | 'singleColumn' | 'singleColumn' | v1 仅单列树展示 |
| treeLazyLoad | boolean | false | 启用 CSRM 懒加载;true 时需 loadTreeChildren |
| hasTreeChildren | HasTreeChildrenFn | — | lazy:true 时即使 source 尚无子孙也展示 expand chevron |
| loadTreeChildren | LoadTreeChildrenFn | — | lazy:首次展开且无已加载子行时异步拉取子数据 |
| treeDragScope | 'siblings' \| 'hierarchy' | 'siblings' | 行拖拽范围,见 行拖拽与层级变更 |
| setDataPath | SetDataPathFn | — | hierarchy 模式下 drag/shortcut 写回路径到 row.data |
| treeHierarchyActions | boolean | true | hierarchy + setDataPath 时,tree 列 hover 展示 上移一级 / 下移一级 菜单 |
回调类型签名:
type GetDataPathFn = (params: { data: RowData }) => string[]
interface TreeValueGetterParams {
data: RowData
dataPath: string[]
treeLevel: number
}
type TreeValueGetterFn = (params: TreeValueGetterParams) => string
interface HasTreeChildrenParams {
data: RowData
dataPath: string[]
treeLevel: number
}
type HasTreeChildrenFn = (params: HasTreeChildrenParams) => boolean
interface LoadTreeChildrenParams {
parentRowId: BusinessRowId
parentData: RowData
dataPath: string[]
treeLevel: number
signal: AbortSignal // 折叠 / destroy 时可 abort
}
type LoadTreeChildrenFn = (
params: LoadTreeChildrenParams,
) => Promise<RowData[] | void> | RowData[] | void
interface SetDataPathParams {
data: RowData
dataPath: string[]
treeLevel: number
previousPath: readonly string[]
}
type SetDataPathFn = (params: SetDataPathParams) => void
setDataPath默认行为:未传入时,若data.pathSegments为数组,内核会自动data.pathSegments = [...dataPath]。业务字段(如org/dept)需自行在setDataPath中同步。
数据模型与 getDataPath
推荐建模方式
方式 A — 路径存于业务字段(推荐,便于持久化):
interface MenuRow {
id: number
pathSegments: string[] // ['系统管理', '用户管理', '角色列表']
title: string
}
const getDataPath: GetDataPathFn = ({ data }) => data.pathSegments方式 B — 路径由字段拼接(适合固定层级列):
const getDataPath: GetDataPathFn = ({ data }) =>
[data.org, data.dept, data.team].filter(Boolean).map(String)方式 C — hierarchy 拖拽后写回(需 setDataPath):
const setDataPath: SetDataPathFn = ({ data, dataPath }) => {
data.pathSegments = [...dataPath]
data.org = dataPath[0]
data.dept = dataPath[1]
data.team = dataPath[2]
}Transaction 与增量更新
树形模式下 applyTransaction 仍操作 flat sourceRows:
// 新增子节点(路径必须含正确父前缀)
api.applyTransaction({
add: [{ id: 'new-fe', org: 'HQ', dept: '研发', team: '前端', name: '新小组', headcount: 5 }],
})
// 删除节点不会自动删子孙——需自行收集子树 id 后 remove
api.applyTransaction({ remove: ['fe', 'be'] })懒加载成功时,内核 内部等价于 applyTransaction({ add: children }) 并 refresh tree 阶段。
getDataPath 与 getData() 的关系
api.getData()返回 flat sourceRows(与 AG Grid 一致),不是 DFS 投影顺序。api.getDataPath(rowId)查询某行的当前路径。- 展示顺序以
rowsToDisplay为准;行索引列对 display 行 连续编号(1…N)。
树列 UI 与系统列
系统列顺序
启用 tree 后,列注入顺序为:
index(可选) → selection(可选) → expand(masterDetail 可选) → tree(__tree__) → 用户列- tree 列默认 左固定(
pinned: 'left'),默认宽 200px,最小 120px。 - 用户
columns中 不得占用保留 colId:__tree__、__index__、__selection__、__expand__、__group__(冲突时 dev 警告并忽略)。
展示内容
| 元素 | 说明 |
|------|------|
| 缩进 | 每级 16px(padding-left = treeLevel × 16) |
| Chevron | 可展开节点显示;叶节点隐藏或占位对齐 |
| 文案 | 默认 dataPath 末段;可用 treeValueGetter 覆盖 |
| Loading | lazy 加载中 chevron 区 spinner + aria-busy |
| Settings 菜单 | treeDragScope: 'hierarchy' 且 setDataPath 可用时,hover 显示 settings 按钮 |
自定义 tree 列
<MagicGrid
tree
:get-data-path="getDataPath"
:auto-tree-column-def="{
headerName: '组织结构',
width: 240,
pinned: 'left',
}"
:tree-value-getter="({ data, dataPath }) => `${dataPath.join(' / ')} · ${data.name}`"
/>隐藏 tree 列(仅保留层级逻辑、自行在业务列渲染缩进):
<MagicGrid tree :get-data-path="getDataPath" :show-tree-column="false" />键盘与无障碍
- 焦点在 tree cell 时:Enter / Space 切换展开/折叠。
- Chevron 带
aria-expanded;lazy loading 时aria-busy="true"。
展开与折叠
用户交互
- 点击 tree 列 chevron 切换当前节点展开/折叠。
- 点击 tree 列头 chevron(与行内同款图标):全部展开 / 全部收起;当所有可展开节点均已展开时 chevron 旋转为展开态,再次点击则
collapseAll()。 - 折叠父节点时,子孙不出现在
rowsToDisplay(非display: none,而是从投影中移除,不参与虚拟化行计数)。
Grid API
| 方法 | 说明 |
|------|------|
| expandNode(rowId) | 展开节点;lazy 模式下若子行未加载会先 await loadTreeChildren |
| collapseNode(rowId) | 折叠节点;会 abort 该节点在途 lazy 请求 |
| isNodeExpanded(rowId) | 查询展开态 |
| expandAll() | 展开 已加载 子树;不会递归触发 lazy load(避免请求风暴) |
| collapseAll() | 折叠全部 |
| getDataPath(rowId) | 返回 string[] 或 undefined |
const api = gridRef.value?.api
api?.expandNode('eng')
api?.collapseNode('hq')
console.log(api?.isNodeExpanded('eng')) // false
console.log(api?.getDataPath('fe')) // ['HQ', '研发', '前端']事件 tree-node-opened
| 字段 | 类型 | 说明 |
|------|------|------|
| rowId | BusinessRowId | 节点 id |
| expanded | boolean | true 展开 / false 折叠 |
| level | number | treeLevel |
| dataPath | string[] | 节点路径 |
| source | 'api' \| 'ui' | API 调用或用户点击 chevron |
树形懒加载
适用于 初始仅加载根节点、按需展开拉取子级的场景。仍为 CSRM(客户端行模型),不是 SSRM 服务端分页树。
启用条件
<MagicGrid
tree
tree-lazy-load
:get-data-path="getDataPath"
:has-tree-children="({ data }) => Boolean(data.hasChildren)"
:load-tree-children="loadChildren"
@tree-children-loading="onLoading"
@tree-children-loaded="onLoaded"
@tree-children-load-failed="onFailed"
/>| 配置 | 必填 | 说明 |
|------|------|------|
| treeLazyLoad: true | 是 | 总闸 |
| loadTreeChildren | 是 | 未提供时 dev 警告,行为退化为 M24 全量 tree |
| hasTreeChildren | 强烈建议 | 控制 尚未加载 时是否显示 chevron |
| getDataPath | 是 | 与全量 tree 相同 |
首次展开时序
用户点击 chevron / expandNode API
→ 若 loadedParentIds 已有 → 直接 map 展开
→ 若 inflight 已有 → 复用同一 Promise
→ emit treeChildrenLoading
→ await loadTreeChildren({ parentRowId, parentData, dataPath, treeLevel, signal })
→ 成功:校验路径 / rowKey 唯一 → applyTransaction({ add }) → refresh tree 阶段
→ emit treeChildrenLoaded → 子孙可见
→ 失败:emit treeChildrenLoadFailed · source 不变 · 保持折叠
→ Abort(折叠/destroy):丢弃 late resolve · 不污染 sourceloadTreeChildren 实现要点
async function loadChildren({
parentRowId,
parentData,
dataPath,
signal,
}: LoadTreeChildrenParams): Promise<RowData[]> {
const res = await fetch(`/api/org/${parentRowId}/children`, { signal })
if (!res.ok) throw new Error('load failed')
const rows = await res.json()
// 每行必须能被 getDataPath 解析,且路径前缀包含 parent 的 dataPath
return rows
}| 规则 | 说明 |
|------|------|
| 幂等 | 同一 parentRowId 成功加载后 不重复请求 |
| 空子树 | 返回 [] → 标记为已加载叶节点 · chevron 消失 |
| 路径校验 | 子行 getDataPath 必须以父路径为前缀;否则 loadFailed |
| AbortSignal | 须在 signal.aborted 时停止;折叠父节点会 abort |
| expandAll | 不批量触发 lazy load |
懒加载事件
| 事件 | 关键字段 |
|------|----------|
| tree-children-loading | parentRowId, dataPath, treeLevel, source |
| tree-children-loaded | parentRowId, children, childCount, source |
| tree-children-load-failed | parentRowId, reason?, aborted? |
排序、筛选与汇总
| 操作 | 树形语义 |
|------|----------|
| 列排序 | 仅在 同一 parentRowId 下兄弟 间重排;不改变 dataPath |
| 列筛选 / Quick Filter | 递归匹配 data 行;某父下子孙全被滤掉 → 父节点隐藏(空枝剪枝) |
| 表尾汇总 | summaryScope: 'displayed' 时仅聚合 可见 data 行(含各层父节点) |
| lazy 未加载分支 | 不参与 filter/sort/drag(RowNode 尚不存在) |
行选择与 groupSelectsChildren
树形模式下行选择配置与 flat 相同,通过 row-selection prop:
<MagicGrid
:row-selection="{ mode: 'multiple', groupSelectsChildren: true }"
/>| groupSelectsChildren | 行为 |
|------------------------|------|
| true(默认) | 选中父 → 递归选中 display 中可见 子孙;取消父 → 递归取消 |
| false | 父子 checkbox 独立;子全选时父 indeterminate;父选中 不自动选子 |
注意:
- 折叠的子孙不参与级联(未投影到 display 的行不在选区内)。
- lazy 加载完成前,父选中 不会 预选尚未加载的子孙。
- 所有 data 行(含非叶节点)均可被选中、编辑。
行拖拽与层级变更
树形行拖拽需开启 indexColumn.showRowDragHandle: true(或列级 drag handle)。与 rowDragManaged 配合使用;配置 asyncRowMutation.move 时拖拽自动 await 持久化。
treeDragScope: 'siblings'(默认)
- drop 仅限同一
parentRowId下兄弟 间换序。 - 跨父 drag → 禁止光标 · 不 emit
rowMoved。 - 不改变
dataPath;仅调整 source 平铺顺序中的兄弟区间。
treeDragScope: 'hierarchy'
允许 跨层级改挂(改父节点),必须提供 setDataPath 写回路径:
| 操作 | 如何触发 |
|------|----------|
| 挂到目标行下(nest) | 拖到 tree 列 子级缩进热区(目标行右侧),或 按住 Alt 再 drop |
| 同级换序 / 改父到根或旁支 | 拖到目标行 同级区域(默认 drop 区) |
| 上移一级 / 下移一级 | tree 列 hover settings-2 菜单(需 treeHierarchyActions !== false) |
层级快捷菜单语义:
| 菜单项 | 行为 | |--------|------| | 上移一级 | 有父节点 → outdent 到父的同级;已是根 → 将 上一个同级节点及其子树 挂到当前节点下 | | 下移一级 | 挂到 display 中 上一个同级节点 的子树末尾 |
菜单项 按节点动态过滤——不可用时隐藏;至少一项可用时才显示 settings 按钮。
asyncRowMutation.move 与 hierarchyChanges
配置了 asyncRowMutation.move 时,拖拽 mouseup 后先 await move(source: 'uiRowDrag'),成功才写 source。
树形改挂、快捷菜单等操作常使 moves 为空 而 hierarchyChanges 非空:
import { getRowDragCommitHierarchy } from '@taocompany/magic-grid'
async function persistMove(params: AsyncRowMutationMoveParams): Promise<void> {
// 推荐:过滤掉仅 treeLevel 变化的项,持久化 parentId + order
const changes = getRowDragCommitHierarchy(params, 'noLevel')
await api.saveHierarchy({ changes })
}RowHierarchyChange 含 rowId、parentRowId、siblingIndex、treeLevel 等字段,由 asyncRowMutation.move 在 source: 'uiRowDrag' 时传入。
树形与其它能力叠加
| 场景 | 预期行为 |
|------|----------|
| 固定列 / 列虚拟化 | tree 列默认左固定;tree cell 仍受列窗口约束 |
| 行虚拟化 | 全部 display 行参与 rowTop 累计;百万行靠虚拟化 |
| Master Detail | detail 行紧跟 master leaf;不参与 tree 路径与子树计数 |
| 合并单元格 | tree 行 不参与 colSpan/rowSpan |
| 单元格编辑 | 所有 data 行可编辑(含父节点);group 模式下的 leaf 限制 不适用 |
| 索引列 | 对 全部 display 行连续编号 |
| cellComments / 框选 / 剪贴板 | 与 flat 相同,基于 display 索引 |
| rowGrouping | 互斥 · 勿双开 |
常见错误与排查
| 现象 | 可能原因 | 处理 |
|------|----------|------|
| 初始化 throw tree: true requires getDataPath | 未传 getDataPath | 添加回调 |
| refresh throw missing parent path | 子行路径缺父节点行 | 补全中间层或修正 path |
| refresh throw 重复路径 | 两行 getDataPath 相同 | 保证路径唯一 |
| 双开 tree + rowGrouping 但无分组 | 设计如此,tree 优先 | 二选一 |
| lazy 展开无 chevron | 未传 hasTreeChildren 且 source 无子行 | 提供 hasTreeChildren |
| lazy 展开无反应 | 未传 loadTreeChildren | 检查 dev 警告 |
| hierarchy drag 无效 | 未传 setDataPath | 实现写回或使用默认 pathSegments |
| 跨父 drag 被拒绝 | treeDragScope: 'siblings' | 改为 hierarchy |
| 选中父但子孙未选中 | 子孙折叠不可见,或 groupSelectsChildren: false | 展开 / 检查配置 |
| expandAll 未加载 lazy 子级 | 设计限制 | 逐节点 expand 或预加载 |
相关 API 索引:Props · 树形表格 · Events · 树形表格 · GridApi · expandNode。
默认配置
以下为 <MagicGrid> 未显式传入 prop 时的生效值。部分 prop 在组件层与内核层默认不同(标注 MG = MagicGrid 组件层覆盖),使用时以组件行为为准。
尺寸 preset(size)
rowHeight / headerHeight / statusBarHeight(statusBarHeight: 'auto' 时)未显式传入时,由 size 推导:
| size | 行高 | 表头高 | 状态栏高 | 字号 | 间距 | 圆角(rounded: true 时) |
|--------|------|--------|----------|------|------|---------------------------|
| mini | 20 | 20 | 20 | 12 | 4 | 4 |
| small | 24 | 24 | 24 | 12 | 8 | 8 |
| default | 32 | 32 | 32 | 12 | 8 | 8 |
| large | 40 | 40 | 40 | 14 | 12 | 8 |
基础与外观
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| rowKey | 'id' | 行主键字段 |
| height / width | '100%' | 容器尺寸;number 或纯数字字符串(如 "420")自动补 px |
| stripe | false | 斑马纹 |
| border | 'border' | 全网格线 |
| theme | 'light' | 亮色主题 |
| size | 'default' | 尺寸 preset |
| rounded | false | 无圆角(0) |
| rowHeight / headerHeight | — | 跟随 size preset |
| summaryRowHeight | — | 跟随 rowHeight |
对齐
| 配置项 | 默认值 |
|--------|--------|
| headerAlign / headerValign | 'center' |
| align / valign | 'center' |
| footerAlign / footerValign | 'center' |
虚拟化与导航
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| rowBuffer | 10 | 行虚拟化缓冲行数 |
| scrollEndFlushMs | 0 | 滚动停止后 flush RAF(ms);0 = 关闭 |
| frameBudgetMs | 60 | 活跃滚动帧预算(ms) |
| scrollEndFrameBudgetMs | -1 | idle flush 帧预算;-1 = 一次跑完 |
| cellRendererDefer | 'always' | cellRenderer 调度策略 |
| deferRowDestroyOnScroll | false | 滚动 active 期间延迟行 destroy |
| rendererFrameBudgetMs | 20 | 滚动 active 时 f1 每帧保底预算(ms) |
| cellRendererPresentation | 'deferred' | Vue renderer 呈现策略 |
| navigateHeader | false | 不允许焦点进入表头 |
| navigateFooter | false | 不允许焦点进入表尾 |
| enableHeaderHighlight | true | 框选时表头列高亮 |
| enableIndexColumnHighlight | true | 框选时索引列高亮 |
索引列
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| showIndexColumn | false | 不显示索引列 |
| indexColumn.label | '' | 表头文案 |
| indexColumn.width | 40 | 列宽 px(最小 40) |
| indexColumn.start | 1 | 起始序号 |
| indexColumn.focusMode | 'multiple' | 辅助定位模式 |
| indexColumn.syncToSelectionColumn | true (MG) | 索引定位单向同步行选择;用户点击索引列或 setIndexFocus(mode: 'default')时生效 |
| indexColumn.showRowDragHandle | false | 不显示行拖拽把柄 |
| indexColumn.enableRowResizer | false | 不可拖拽调整行高 |
行选择
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| rowSelection | 'single' | 单选模式 |
| selectionColumn.width | 40 | 列宽 px |
| selectionColumn.selectAllLabel | '全选' | 全选 checkbox aria-label |
| reserveSelection | false | 数据刷新后是否保留选中行;离屏选中可用 clearRowSelection({ scope: 'all' }) 清空 |
rowSelection 对象形式时,groupSelectsChildren 默认 true(tree 模式父节点级联子孙)。
表尾汇总
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| showSummary | false | 不展示汇总行 |
| summaryScope | 'displayed' | 按当前可见行汇总 |
排序 / 筛选 / 列操作
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| sortable | false | 全列默认不可排序 |
| filterable | false | 全列默认不可筛选 |
| resizable | true | 全列默认可调整列宽 |
| columnMovable | true | 全列默认可拖拽重排 |
| quickFilterText | '' | 无 quick filter |
| floatingFilter | false | 无 floating filter 行 |
| filterSetValueMode | 'current' | 值选择勾选投影模式 |
| filterSetDateLayoutMode | 'tree' | 日期列值选择树形展示 |
| colResizeDefault | — | 未启用 Shift 邻列补偿 |
| skipHeaderOnAutoSize | false | auto-size 含表头宽度 |
| autoSizePadding | 16 | auto-size 额外 padding(px) |
| suppressMoveWhenColumnDragging | false | drag 过程中 live move |
| suppressColumnMoveAnimation | false | 列移动有过渡动画 |
| allowCrossLaneColumnMove | false | 不可跨 fixed lane 移动 |
| showUnsortedSortHintOnHover | false | 未排序列 hover 无双三角提示 |
编辑
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| editBehavior | 'cell' | 单格编辑 |
| editType | 'singleClick' | 单击进入编辑 |
| invalidEditValueMode | 'block' | 校验失败保持编辑态 |
行拖拽与行高
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| rowDragManaged | true | managed 拖拽实时改序 |
| asyncRowMutation.move | — | 拖拽与 API 均 await 持久化后再改本地 |
| rowHeightMin | — | 跟随 size / rowHeight |
| rowHeightMax | — | 无上限 |
合并 / 展开 / 分组 / 树
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| enableCellSpan | false | 不启用单元格合并 |
| masterDetail | false | 不启用主从展开 |
| masterDefaultExpanded | 0 | 默认不展开(启用 masterDetail 后) |
| detailRowHeight | 200 | 详情行高度 px |
| detailRowAutoHeight | false | 详情行固定高度 |
| embedFullWidthRows | false | 详情 overlay 不随横滚 |
| showExpandColumn | false | 不展示专用展开列 |
| rowGrouping | false | 不启用行分组 |
| groupDefaultExpanded | -1 | 全部分组默认展开 |
| showGroupHeader / showGroupFooter | false | 不展示分组头/尾行 |
| groupDisplayType | 'singleColumn' | 单列分组展示 |
| showGroupColumn | false | 不展示 auto group 列 |
| tree | false | 不启用树形表格 |
| showTreeColumn | true | 展示 tree 系统列(启用 tree 后) |
| treeDragScope | 'siblings' | 树拖拽仅同层兄弟 |
| treeHierarchyActions | true | hierarchy 模式下展示层级快捷菜单 |
| treeDisplayType | 'singleColumn' | 单列树展示 |
| treeLazyLoad | false | 不启用懒加载 |
批注
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| suppressCellComments | false | 不抑制批注 |
| cellCommentTrigger | 'click' | 点击角标查看 |
| cellCommentShowDelay | 180 | hover 展示延迟 ms |
| cellCommentHideDelay | 220 | 离开隐藏延迟 ms |
框选与剪贴板
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| cellSelection | true (MG) | 启用框选(Grid API 直连默认 false) |
| cellSelection.enableColumnSelection | true (MG) | 点击表头选中整列(Grid API 默认 false) |
| cellSelection.suppressMultiRanges | true | 仅允许单个 range |
| cellSelection.handleMode | 'off' | 无 Fill/Range 拖拽柄 |
| cellSelection.direction | 'xy' | fill 方向(handleMode 为 fill 时) |
| cellSelection.fillStrategy | 'copy' | 填充策略 |
| cellSelection.fillReverseStrategy | 'default' | 反拖缩小行为 |
| enableCellCopy | true | Ctrl+C / 复制 API |
| enableCellPaste | false | Ctrl+V / 粘贴 API |
Tooltip
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| enableTooltips | true | 启用溢出 tooltip |
| tooltipShowMode | 'whenTruncated' | 仅溢出时展示 |
| tooltipShowDelay | 500 | 首次 hover 延迟 ms |
| tooltipSwitchShowDelay | 200 | 格间切换延迟 ms |
| tooltipHideDelay | 3000 | 离开后隐藏延迟 ms |
| tooltipInteraction | false | tooltip 不可交互 |
| tooltipMouseTrack | false | tooltip 不跟随鼠标 |
空态 Overlay
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| loading | undefined | 挂载后首次 setData 前自动 loading |
| overlayInteraction | false | overlay 内容不可交互 |
状态栏
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| showStatusBar | true | 显示底部状态栏 |
| showDefaultStatusBarPanels | true | 显示默认左侧面板 |
| statusBarHeight | 'auto' | 跟随 size preset |
| showStatusBarRangeAggregation | true | 框选时展示聚合 |
| statusBarRangeAggregationPosition | 'right' | 聚合 panel 在右栏 |
| statusBarRangeAggregationPrecision | 2 | 平均值/求和各 2 位小数 |
ColumnDef 列级默认
| 字段 | 默认值 | 说明 |
|------|--------|------|
| available | true | 列有效;false 时不进入列模型(表格中无此列) |
| hidden | false | 列可见;true 时仍在列模型中但不渲染(可 API/菜单恢复) |
| sortable / filterable | 继承 Grid 级(默认 false) | 列级显式配置优先 |
| resizable / movable | 继承 Grid 级(默认 true) | 列级显式配置优先 |
| filterType | 'text' | 文本筛选 |
| cellEditorMode | 'overlay' | 编辑 overlay 呈现 |
| editType | 继承 Grid 级 | — |
| useParserForClipboard | true | 粘贴走 valueParser |
| useFormatterForClipboard | true | 复制走 formatter |
| summary | 有 summaryAgg 时为 true | 否则 false |
| 对齐字段 | 'center' | header / body / footer |
Props
各 prop 的默认值汇总见上一节 默认配置。下列按功能分组逐项说明类型、默认值与行为。
MagicGrid Props
基础
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| columns | ColumnDef[] | — | 必填。列定义数组;available: false 的项仍可在 prop 中保留,但不会进入 Grid 列模型 |
| data | RowData[] | — | 必填。行数据(普通对象,禁止 reactive 深代理) |
| rowKey | string | 'id' | 行主键字段名,用于行池复用与增量更新 |
| height | string \| number | '100%' | 容器高度;number / 纯数字字符串 → px,亦支持 % / vh 等 |
| width | string \| number | '100%' | 容器宽度;解析规则同 height |
外观
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| stripe | boolean | false | 斑马纹 |
| border | 'border' \| 'none' \| 'linear' | 'border' | 边框样式:border 全网格线;none 无单元格线;linear 仅底部分隔线 |
| theme | 'light' \| 'dark' | 'light' | 主题 preset |
| size | 'mini' \| 'small' \| 'default' \| 'large' | 'default' | 尺寸 preset(影响行高、字号、间距等) |
| rounded | number \| boolean | false | 容器圆角:false/0 无圆角;true 跟随 size;number 自定义 px |
| rowHeight | number | — | 固定行高(px);显式传入时覆盖 size preset |
| headerHeight | number | — | 表头高度(px);显式传入时覆盖 size preset |
| rowStyle | RowStyle \| RowStyleFn | — | 行级样式(对象=全表同色;函数=按行);作用于表体用户数据列与行选择列 |
对齐(全局默认)
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| headerAlign | 'left' \| 'center' \| 'right' | 'center' | 表头水平对齐 |
| headerValign | 'top' \| 'center' \| 'bottom' | 'center' | 表头垂直对齐 |
| align | 'left' \| 'center' \| 'right' | 'center' | 表体水平对齐 |
| valign | 'top' \| 'center' \| 'bottom' | 'center' | 表体垂直对齐 |
| footerAlign | 'left' \| 'center' \| 'right' | 'center' | 表尾汇总水平对齐 |
| footerValign | 'top' \| 'center' \| 'bottom' | 'center' | 表尾汇总垂直对齐 |
虚拟化与导航
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| rowBuffer | number | 10 | 行虚拟化缓冲行数 |
| scrollEndFlushMs | number | 0 | 滚动停止 debounce 后 flush RAF(ms);0 = 关闭 |
| frameBudgetMs | number | 60 | 活跃滚动时每帧任务预算(ms) |
| scrollEndFrameBudgetMs | number | -1 | scroll idle flush 帧预算;-1 = 一次跑完 |
| cellRendererDefer | 'always' \| 'never' \| 'sync-only' | 'always' | cellRenderer 是否进入 f1 异步队列 |
| deferRowDestroyOnScroll | boolean | false | 滚动 active 期间延迟行 destroy + Vue unmount |
| rendererFrameBudgetMs | number | 20 | 滚动 active 时为 f1 预留的每帧保底预算(ms);0 = 与 p1/p2 共享 |
| cellRendererPresentation | 'immediate' \| 'deferred' \| 'placeholder-then-vue' | 'deferred' | Vue renderer 呈现策略;详见 Cell Renderer 滚动渲染 |
| navigateHeader | boolean | false | 是否允许键盘/鼠标将焦点导航到表头 |
| navigateFooter | boolean | false | 是否允许焦点导航到表尾汇总行(需 showSummary: true) |
| enableHeaderHighlight | boolean | true | 表头高亮 |
| enableIndexColumnHighlight | boolean | true | 索引列高亮 |
索引列
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| showIndexColumn | boolean | false | 是否显示最左侧索引列;asyncRowMutation await 期间 loading 亦依赖此项 |
| indexColumn | IndexColumnOptions | — | 索引列配置(showIndexColumn=true 时生效) |
IndexColumnOptions 字段:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| label | string | '' | 表头文案 |
| width | number | 40 | 列宽 px(最小 40) |
| start | number | 1 | 起始序号(1-based 展示 = rowIndex + start) |
| focusMode | 'single' \| 'multiple' | 'multiple' | 辅助定位模式 |
| syncToSelectionColumn | boolean | false(MagicGrid 组件层默认 true) | 索引列定位是否单向同步到行选择列;仅当 focusMode 与 rowSelection 同为 single 或同为 multiple 时生效。用户在索引列上操作,或 API setIndexFocus(mode: 'default')时同步;点击其他区域清除索引定位、行删除 / rowId 迁移等不同步 |
| index | (rowIndex) => number \| string | — | 自定义序号展示 |
| showRowDragHandle | boolean | false | 在索引列显示行拖拽把柄 |
| enableRowResizer | boolean | false | 索引列底边可拖拽调整行高 |
| headerAlign / headerValign / align / valign / footerAlign / footerValign | GridHorizontalAlign / GridVerticalAlign | 'center' | 对齐配置 |
行选择
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| rowSelection | 'single' \| 'multiple' \| false \| RowSelectionConfig | 'single' | 行选择模式;false 禁用 |
| selectionColumn | SelectionColumnOptions | — | 行选择列配置 |
| selectable | SelectableFn | — | 行 checkbox 是否可勾选;省略时全部可选 |
| reserveSelection | boolean | false | 数据刷新后是否保留选中行;离屏选中可用 clearRowSelection({ scope: 'all' }) 清空 |
| isRowDisabled | boolean \| IsRowDisabledFn | — | 行级禁用(该行全部数据列 disabled) |
RowSelectionConfig:
interface RowSelectionConfig {
mode: 'single' | 'multiple'
groupSelectsChildren?: boolean // tree 模式下选中父节点是否级联子孙,默认 true
}SelectionColumnOptions 字段:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| width | number | 40 | 列宽 px(最小 40) |
| selectAllLabel | string | '全选' | 表头全选 checkbox 的 aria-label |
| rowLabel | (rowIndex) => string | — | 行 checkbox 的 aria-label 工厂 |
| headerAlign / headerValign / align / valign / footerAlign / footerValign | GridHorizontalAlign / GridVerticalAlign | 'center' | 对齐配置 |
表尾汇总
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| showSummary | boolean | false | 是否展示表尾汇总行 |
| summaryScope | 'displayed' \| 'all' | 'displayed' | 汇总范围:displayed 当前可见行;all 全量 sourceRows |
| summaryRowHeight | number | — | 汇总行高度 px;未传时跟随 rowHeight |
| summaryMethod | SummaryMethod | — | 全局汇总方法(优先级高于列级 summaryAgg) |
排序
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| defaultSort | SortModelItem[] | — | 初始排序(挂载时应用一次;v1 仅使用首项) |
| sortable | boolean | false | 是否允许表头排序;列级 columns[].sortable 优先于本配置;系统列恒为 false |
| showUnsortedSortHintOnHover | boolean | false | 未排序 sortable 列 hover 显示 faint 双三角 |
列操作
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| columnMovable | boolean | true | 是否允许表头拖拽重排列 |
| resizable | boolean | true | 是否允许拖拽调整列宽(列级 resizable 优先) |
| colResizeDefault | 'shift' | — | Shift 模式:拖拽列宽时相邻列反向补偿,总宽不变 |
| skipHeaderOnAutoSize | boolean | false | 双击 resize 把柄 auto-size 时跳过表头宽度 |
| autoSizePadding | number | 16 | auto-size 内容测量额外 padding(px) |
| autoSizeStrategy | AutoSizeStrategy | — | 挂载/首屏 auto-size 策略(见 AutoSizeStrategy) |
| suppressMoveWhenColumnDragging | boolean | false | true → 仅 mouseup 提交列序 |
| suppressColumnMoveAnimation | boolean | false | 关闭列移动 transition |
| allowCrossLaneColumnMove | boolean | false | 允许 drag/API 跨 fixed lane 并更新列 fixed |
筛选
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| filterable | boolean | false | 是否允许列筛选;列级 columns[].filterable 优先于本配置;系统列恒为 false |
| quickFilterText | string | '' | Grid 级 quick filter 文本(对 filterable 用户列 OR 式 contains) |
| floatingFilter | boolean | false | 表头下方 floating filter 行(仅对 filterable 列渲染输入框) |
| filterSetValueMode | 'reserve' \| 'current' | 'current' | 值选择搜索时的勾选投影模式 |
| filterSetDateLayoutMode | 'list' \| 'tree' | 'tree' | 日期列值选择展示方式 |
编辑
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| editBehavior | CellEditBehavior | 'cell' | 编辑范围:单格 / 整行 |
| editType | CellEditType | 'singleClick' | 进入编辑态的触发方式 |
| invalidEditValueMode | 'block' \| 'revert' \| 'keep' | 'block' | 校验失败后:block 保持编辑;revert 退出并恢复旧值;keep 退出编辑但保留无效值 |
| rowValidator | RowValidator | — | 行编辑跨字段校验 |
| cellEditorRegistry | Record<string, CellEditorFn> | — | 实例级命名编辑器注册表 |
| asyncRowMutation | AsyncRowMutationHandlers | — | 异步行 CRUD 持久化钩子(见 AsyncRowMutationHandlers) |
行拖拽与行高
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| rowDragManaged | boolean | true | managed 行拖拽:拖拽过程中实时改 source 顺序 |
| asyncRowMutation | AsyncRowMutationHandlers | — | 含 move 时编程式 move 与索引列拖拽共用;await 期间索引列 loading(须 showIndexColumn) |
| getRowHeight | GetRowHeightFn | — | 行级动态高度(无 DOM) |
| rowHeightMin | number | — | 行高下限 px |
| rowHeightMax | number | — | 行高上限 px |
合并单元格
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| enableCellSpan | boolean | false | 启用单元格合并(列级 colSpan / rowSpan / spanRows) |
主从展开行
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| masterDetail | boolean | false | 启用主从展开行 |
| isRowMaster | IsRowMasterFn | — | 是否为主行(可展示 expand 控件) |
| masterDefaultExpanded | number | — | 默认展开层级:0=无;1=第一层;-1=全部 |
| detailRowHeight | number \| DetailRowHeightFn | — | 详情行固定高度 px |
| detailRowAutoHeight | boolean | — | 详情行按内容自动撑高 |
| embedFullWidthRows | boolean | — | true:详情嵌入 center lane 随横滚 |
| showExpandColumn | boolean | — | 最左展示专用展开列 |
| getDetailRowData | GetDetailRowDataFn | — | 异步提供详情区数据 |
| detailCellRenderer | DetailCellRendererFn | — | 自定义详情行渲染器(与 #detail-row 插槽二选一) |
行分组
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| rowGrouping | boolean | false | 启用行分组 |
| groupDefaultExpanded | number | -1 | 默认展开分组层级:0=全折叠;1=第一层;-1=全部 |
| showGroupHeader | boolean | false | 展示 groupHeader 分组标题行 |
| showGroupFooter | boolean | false | 为每个已展开分组展示 footer 汇总行 |
| groupDisplayType | 'singleColumn' | 'singleColumn' | 分组展示模式(v1 仅 singleColumn) |
| showGroupColumn | boolean | false | 展示 auto group 系统列 |
| autoGroupColumnDef | Partial<ColumnDef> | — | 覆盖 auto group 列 colDef |
| groupKeyCreator | GroupKeyCreatorFn | — | 分组键归一化 |
| groupComparator | GroupComparatorFn | — | 同级 group 节点排序 |
| groupFooterLabel | string | — | groupFooter 首列展示标签 |
| groupCellRenderer | GroupCellRendererFn | — | 自定义分组单元格渲染器 |
编辑:启用单元格编辑时,仅 leaf 数据行可进入编辑态;
groupHeader/groupFooter不渲染 inline 或 overlay 编辑器(由isCellEditable+cellCtrl共同保证)。
树形表格
完整消费端指南见 树形表格 专章(概念、懒加载、拖拽、排查)。下表为 Props 速查。
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| tree | boolean | false | 启用树形表格(与 rowGrouping 互斥) |
| getDataPath | GetDataPathFn | — | 树形路径回调(tree: true 时 必填) |
| groupDefaultExpanded | number | -1 | 默认展开层级:0 全折叠 · 1 第一层 · -1 全部(tree / group 共用) |
| treeDragScope | 'siblings' \| 'hierarchy' | 'siblings' | 树形拖拽范围;hierarchy 允许跨父改挂(需 setDataPath) |
| setDataPath | SetDataPathFn | — | hierarchy 模式下写回 dataPath 到行数据 |
| treeHierarchyActions | boolean | true | hierarchy 时在 tree 列展示 上移一级 / 下移一级 菜单 |
| showTreeColumn | boolean | true | 展示 tree 系统列(colId __tree__) |
| autoTreeColumnDef | Partial<ColumnDef> | — | 覆盖 tree 系统列 colDef |
| treeValueGetter | TreeValueGetterFn | — | 自定义 tree 列展示值(缺省为 dataPath 末段) |
| treeDisplayType | 'singleColumn' | 'singleColumn' | 树节点展示列模式 |
| treeLazyLoad | boolean | false | 启用树形懒加载(CSRM · 需 loadTreeChildren) |
| hasTreeChildren | HasTreeChildrenFn | — | lazy:节点是否可能有未加载子行(控制 chevron) |
| loadTreeChildren | LoadTreeChildrenFn | — | lazy:首次展开时拉取子数据 |
单元格批注
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| cellCommentsDataSource | CellCommentsDataSource | — | 批注数据源;提供即启用(见 CellCommentsDataSource) |
| suppressCellComments | boolean | false | 全局抑制批注交互 |
| cellCommentTrigger | 'click' \| 'hover' | 'click' | 查看已有批注的触发方式 |
| cellCommentShowDelay | number | 180 | hover 模式展示延迟 ms |
| cellCommentHideDelay | number | 220 | 离开 cell/popup 后隐藏延迟 ms |
框选与剪贴板
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| cellSelection | boolean \| CellSelectionOptions | true | 单元格框选;MagicGrid 默认开启、enableColumnSelection 为 true、handleMode 为 off;Grid API 未传时默认关闭 |
| enableCellCopy | boolean | true | Ctrl+C / copySelectedRangeToClipboard |
| enableCellPaste | boolean | false | Ctrl+V / pasteFromClipboard |
| processCellForClipboard | ProcessCellForClipboardFn | — | 复制单格时自定义导出值 |
| processCellFromClipboard | ProcessCellFromClipboardFn | — | 粘贴单格时预处理 clipboard 字符串 |
| processDataFromClipboard | ProcessDataFromClipboardFn | — | 整表粘贴前处理 TSV 矩阵;return null 取消粘贴 |
CellSelectionOptions 字段(cellSelection 为对象时):
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| suppressMultiRanges | boolean | true | true 时仅允许单个 range |
| enableColumnSelection | boolean | MagicGrid true / Grid API false | 点击表头选中整列 |
| handleMode | 'off' \| 'fill' \| 'range' | 'off' | Fill / Range 拖拽柄 |
| direction | 'x' \| 'y' \| 'xy' | 'xy' | handleMode: 'fill' 时填充方向 |
| fillStrategy | 'auto' \| 'copy' | 'copy' | 'auto':数字递增、非数字复制;'copy':始终复制源边值 |
| fillReverseStrategy | 'default' \| 'clear' | 'default' | 反拖缩小时:'default' 不处理;'clear' 置空缩出初始选区的格 |
| setFillValue | (params: FillOperationParams) => unknown | — | 自定义填充值;缺省按 fillStrategy |
FillOperationParams:{ rowNode, column, baseValue, step, direction }。
框选行为要点:
- 鼠标拖拽或 Shift+方向键扩展选区;
suppressMultiRanges: true时仅保留单个 range。 enableColumnSelection: true时点击表头选中整列;MagicGrid 默认开启。handleMode: 'fill'启用填充柄;'range'启用范围扩展柄;'off'无柄(MagicGrid 默认)。- Delete 键清空选区内可编辑格,触发
cell-selection-delete-start/cell-selection-delete-end。 - Ctrl+C /
copySelectedRangeToClipboard复制 TSV;Ctrl+V /pasteFromClipboard粘贴(需enableCellPaste: true)。
Tooltip
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| enableTooltips | boolean | true | 是否启用溢出 tooltip |
| tooltipShowMode | 'whenTruncated' \| 'always' \| 'never' | 'whenTruncated' | 溢出 tooltip 显示策略 |
| tooltipShowDelay | number | 500 | 首次 hover 展示延迟 ms |
| tooltipSwitchShowDelay | number | 200 | 格间切换展示延迟 ms |
| tooltipHideDelay | number | 3000 | 离开后隐藏延迟 ms |
| tooltipInteraction | boolean | — | tooltip 是否可交互 |
| tooltipMouseTrack | boolean | — | tooltip 是否跟随鼠标 |
| tooltipComponent | TooltipComponentType | — | 自定义 tooltip 组件(与 #tooltip 插槽二选一) |
| tooltipComponentParams | Record<string, unknown> | — | tooltip 组件额外参数 |
空态 Overlay
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| loading | boolean | — | 显示 loading overlay;undefined 为挂载后首次 setData 前自动 loading |
| suppressOverlays | OverlayType[] | — | 逐项抑制内置 overlay |
| suppressLoadingOverlay | boolean | — | 抑制 loading overlay |
| suppressNoRowsOverlay | boolean | — | 抑制无数据 overlay |
| suppressNoMatchingRowsOverlay | boolean | — | 抑制筛选无匹配 overlay |
| overlayLoadingTemplate | string | — | loading 模板 HTML |
| overlayNoRowsTemplate | string | — | 无数据模板 HTML |
| overlayNoMatchingRowsTemplate | string | — | 筛选无匹配模板 HTML |
| loadingOverlayComponent | OverlayComponentType | — | 自定义 loading 组件 |
| loadingOverlayComponentParams | Record<string, unknown> | — | loading 组件额外参数 |
| noRowsOverlayComponent | OverlayComponentType | — | 自定义无数据组件 |
| noRowsOverlayComponentParams | Record<string, unknown> | — | 无数据组件额外参数 |
| noMatchingRowsOverlayComponent | OverlayComponentType | — | 自定义筛选无匹配组件 |
| noMatchingRowsOverlayComponentParams | Record<string, unknown> | — | 筛选无匹配组件额外参数 |
| overlayComponent | OverlayComponentType | — | 通用 overlay 组件 |
| overlayComponentParams | Record<string, unknown> | — | 通用 overlay 组件额外参数 |
| overlayInteraction | boolean | — | overlay 内容是否可交互 |
状态栏
| Prop | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| showStatusBar | boolean | true | 是否显示底部状态栏 |
| statusBarHeight | 'auto' \| number | 'auto' | 状态栏高度;auto 跟随 size preset |
| showDefaultStatusBarPanels | boolean | true | 显示默认状态栏左侧面板(行数/筛选态/选中数);false 时仍可自定义 #status-bar-left |
| showStatusBarRangeAggregation | boolean | true | 框选时在状态栏展示平均值/计数/求和 |
| statusBarRangeAggregationPosition | 'left' \| 'right' | 'right' | 框选聚合 panel 位置(左栏/右栏内侧) |
| statusBarRangeAggregationPrecision | number \| { average?: number; sum?: number } | 2 | 平均值/求和展示小数位数 |
Grid 级默认与列级覆盖
以下 Grid Prop 可一次性为所有用户列设定默认行为;列级字段显式配置时以列为准(对齐 AG Grid defaultColDef 语义):
| Grid Prop | 列级字段 | 默认值 | 说明 |
|-----------|----------|--------|------|
| sortable | columns[].sortable | false | 表头点击排序 |
| filterable | columns[].filterable | false | 列筛选 / 表头 filter 把柄 / quick filter 参与列 |
| resizable | columns[].resizable | true | 拖拽调整列宽 |
| columnMovable | columns[].movable | true | 表头拖拽重排列 |
系统列(索引 / 行选择 / 展开 / 分组等)不受 Grid 默认影响,相关能力恒为关闭。
运行时修改 :sortable / :filterable / :resizable 会热更新列模型并刷新表头(无需重建 Grid)。
<!-- 全列默认可排序、可筛选;金额列单独关闭 -->
<MagicGrid
:columns="[
{ prop: 'name', label: '名称' },
{ prop: 'amount', label: '金额', sortable: false, filterable: false },
]"
sortable
filterable
floating-filter
/>ColumnDef 列定义
每列通过 columns 数组传入。key 为列唯一标识,缺省等于 prop。
标识与展示
| 字段 | 类型 | 说明 |
|------|------|------|
| key | string | 列唯一标识(colId),缺省等于 prop |
| prop | string | 数据字段 |
| label | string | 表头文案 |
列有效性与显隐
通过 available 与 hidden 控制列是否参与表格。二者均可在 columns prop 中动态修改;Grid 会重解析列模型并刷新布局。
| 字段 | 类型 | 默认 | 说明 |
|------|------|------|------|
| available | boolean | true | false 时该列不存在于表格(解析前从列模型裁剪 · 不参与布局/DOM · 无 setColumnsHidden) |
| hidden | boolean | false | true 时列仍在列模型中,仅不渲染(可通过 setColumnsHidden / 列菜单 / 列设置面板恢复) |
语义对照:
| | available: false | hidden: true |
|---|-------------------|----------------|
| getColumns() | 不含该列 | 含该列 |
| getDisplayedColumns() | 不含 | 不含 |
| DOM / 布局 | 不参与 | 不参与 |
| setColumnsHidden | 不适用(列不在模型中) | 可恢复显示 |
| sort / filter 模型 | 不应再引用该 colId | 仍可保留 · 表头无 UI |
| 列设置面板 | 不出现(未注册进模型) | 出现在「隐藏」分组 |
| 典型用途 | 按权限/场景裁剪列定义 | 用户临时隐藏列 |
const columns: ColumnDef[] = [
{ prop: 'name', label: '名称' },
// 表格中完全没有这一列(行数据字段可保留)
{ prop: 'internalCode', label: '内部编码', available: false },
// 列仍在模型中,默认隐藏,API/菜单可恢复
{ prop: 'note', label: '备注', hidden: true },
]
// hidden 列:全量 vs 展示
api.getColumns().map((c) => c.colId) // 含 note
api.getDisplayedColumnIds() // 不含 note(除非已显示)
// available: false 的列不在 getColumns() 中
api.getColumns().some((c) => c.colId === 'internalCode') // false修改 columns 中某列的 available 或 hidden 后,Grid 会走 setColumns 重解析。available 集合变化时列顺序按 ColumnDef 声明序重置;同集合热更新(如仅改 width/label)仍保留 runtime 顺序(含用户拖拽)。hidden 在 columnDefs 未改 hidden 声明时,会保留运行时 API/菜单设置的值(与 Phase 22 列显隐语义一致)。
尺寸
| 字段 | 类型 | 说明 |
|------|------|------|
| width | number | 固定列宽 px |
| minWidth | number | 最小列宽 px |
| maxWidth | number | 最大列宽 px |
| flex | number | 弹性列宽权重 |
行为
| 字段 | 类型 | 说明 |
|------|------|------|
| sortable | boolean | 是否可排序;缺省继承 Grid sortable(默认 false) |
| comparator | ColumnComparatorFn | 自定义排序比较器(asc 语义;desc 由内核取反) |
| filterable | boolean | 是否可筛选;缺省继承 Grid filterable(默认 false) |
| filterType | ColumnDataFilterType | 筛选数据类型;默认 text |
| filterParams | FilterParams | 列级 filter 参数(见 FilterParams) |
| filterFormatter | (row) => unknown | 筛选用取值;缺省 formatter → valueGetter → prop |
| editable | boolean \| (row) => boolean | 是否可编辑 |
| resizable | boolean | 是否允许拖拽调整列宽;缺省继承 Grid resizable(默认 true) |
| suppressAutoSize | boolean | 禁止 resize 把柄 dblclick / API auto-size |
| suppressSizeToFit | boolean | 禁止参与 sizeColumnsToFit |
| fixed | 'left' \| 'right' \| null | 固定列 |
| movable | boolean | 是否允许表头拖拽重排;缺省继承 columnMovable |
| rowDrag | boolean | 该列单元格作为行拖拽起点 |
| rowExpand | boolean | 在该列渲染 expand/collapse 控件 |
| autoHeight | boolean | 该列内容撑开行高 |
行分组(需 rowGrouping: true)
| 字段 | 类型 | 说明 |
|------|------|------|
| rowGroup | boolean | 该列参与行分组 |
| rowGroupIndex | number | 多级分组顺序(小者优先) |
| groupAgg | SummaryAgg | 分组 footer 行的聚合 |
| showGroupHeaderCell | boolean | 在该列渲染 groupHeader 单元格 |
| showGroupFooterCell | boolean | 在该列渲染 groupFooter 标签 |
| groupFooterLabel | string | 覆盖 Grid groupFooterLabel 的本列小计文案 |
合并单元格(需 enableCellSpan: true)
| 字段 | 类型 | 说明 |
|------|------|------|
| colSpan | ColSpanFn | 横向合并列数(≥1) |
| rowSpan | RowSpanFn | 纵向合并行数(≥1);与 spanRows 互斥时本字段优先 |
| spanRows | boolean \| SpanRowsFunc | 相邻等值自动纵向合并 |
数据转换与渲染
| 字段 | 类型 | 说明 |
|------|------|------|
| valueGetter | (row, value) => unknown | 取值转换 |
| formatter | (row, value) => string | 展示格式化 |
| cellRenderer | CellRendererFn | 自定义单元格渲染器(函数;Vue 组件通过 #cell-{colId} 插槽) |
| cellRendererMount | 'vue' \| 'sync' | 列级 renderer 挂载类型;配合 cellRendererDefer: 'sync-only' 使用 |
| cellEditor | CellEditorDef | 自定义单元格编辑器(函数、内置 text/number/checkbox/switch、或命名引用) |
| cellEditorParams | CellEditorParamsInput | 列级编辑器配置;checkbox / switch / 自定义编辑器统一入口(见 47-cell-editor-params) |
| cellEditorMode | 'overlay' \| 'inline' | 编辑器呈现方式;默认 overlay |
| valueParser | (value, params) => unknown | 提交前解析编辑值 |
| valueSetter | (params) => boolean \| Promise<boolean> | 自定义写回逻辑;返回 false 拒绝提交 |
| cellCommitted | CellCommittedHandler | 值成功写回后的列级副作用;联动字段推荐 context.api.patchRow;见 44-phase29 |
| editType | CellEditType | 编辑触发策略;缺省继承 grid 级配置 |
校验
| 字段 | 类型 | 说明 |
|------|------|------|
| cellValidator | CellValidator | 手写校验(优先级高于 validationRules) |
| validationRules | ValidationRules | async-validator 规则 |
| validationRequired | boolean | 必填列;表头文字前显示红色 *(缺省由 validationRules.required 推导) |
剪贴板
| 字段 | 类型 | 说明 |
|------|------|------|
| suppressPaste | boolean \| SuppressPasteFn | 禁止粘贴 |
| useParserForClipboard | boolean | 粘贴是否走 valueParser;默认 true |
| useFormatterForClipboard | boolean | 复制是否走 formatter;默认 true |
汇总
| 字段 | 类型 | 说明 |
|------|------|------|
| summary | boolean | 是否参与表尾汇总;缺省:有 summaryAgg 则为 true |
| summaryAgg | SummaryAgg | 表尾汇总聚合:sum/avg/min/max/count 或自定义函数 |
| summaryFormatter | (value) => string | 汇总格专用 formatter |
对齐
| 字段 | 类型 | 说明 |
|------|------|------|
| headerAlign / headerValign | GridHorizontalAlign / GridVerticalAlign | 表头对齐;默认 center |
| align / valign | GridHorizontalAlign / GridVerticalAlign | 表体对齐;默认 center |
| footerAlign / footerValign | GridHorizontalAlign / GridVerticalAlign | 表尾对齐;默认 center |
禁用与样式
| 字段 | 类型 | 说明 |
|------|------|------|
| disabled | boolean | 列级禁用:该列全部数据行 disabled |
| cellDisabled | boolean \| CellDisabledFn | 格级禁用;与 disabled / isRowDisabled 叠加 |
| cellStyle | CellStyle \| CellStyleFn | 列级静态背景或格级 cellStyle 回调 |
| suppressCellComments | boolean \| SuppressCellCommentFn | 抑制该列(或特定行)的批注新建/编辑/删除 |
Tooltip
| 字段 | 类型 | 说明 |
|------|------|------|
| tooltipField | string | 读 row.data[field] 作为 tooltip |
| tooltipValueGetter | TooltipValueGetter | 自定义 tooltip 文案 |
| headerTooltip | string | 表头静态 tooltip |
| headerTooltipValueGetter | HeaderTooltipValueGetter | 表头自定义 tooltip |
| suppressTooltip | boolean | 抑制该列溢出 tooltip |
| tooltipComponent | TooltipComponentType | 列级自定义 tooltip 组件 |
| tooltipComponentParams | Record<string, unknown> | tooltip 组件参数 |
Options 类型参考
下列类型均可从 @taocompany/magic-grid 导入,供 Props、GridApi 与事件 payload 使用。
IndexColumnOptions
索引列配置,通过 indexColumn prop 传入(showIndexColumn=true 时生效)。
配置了 asyncRowMutation.update / remove / move 时,await 期间受影响行会在索引列显示 loading spinner(.mg-cell--index-loading)。
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| label | string | '' | 表头文案 |
| width | number | 40 | 列宽 px(最小 40) |
| start | number | 1 | 起始序号(1-based 展示 = rowIndex + start) |
| focusMode | 'single' \| 'multiple' | 'multiple' | 辅助定位模式 |
| syncToSelectionColumn | boolean | core false / MagicGrid true | 索引列定位单向同步到行选择列;用户点击索引列或 setIndexFocus(mode: 'default')时生效 |
| index | (rowIndex) => number \| string | — | 自定义序号展示 |
| showRowDragHandle | boolean | false | 在索引列显示行拖拽把柄 |
| enableRowResizer | boolean | false | 索引列底边可拖拽调整行高 |
| headerAlign / headerValign / align / valign / footerAlign / footerValign | GridHorizontalAlign / GridVerticalAlign | 'center' | 对齐配置 |
SetIndexFocusOptions
setIndexFocus 的可选第二参数:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| mode | 'default' \| 'manual' | 'default' | default:与用户点击索引列一致,按 grid syncToSelectionColumn 决定是否同步行选择列;manual:由 syncToSelectionColumn 显式控制 |
| syncToSelectionColumn | boolean | false(仅 mode: 'manual' 时生效) | 是否同步行选择列;可覆盖 grid 配置 |
api.setIndexFocus(2) // 默认模式
api.setIndexFocus(2, { mode: 'default' }) // 同上
api.setIndexFocus(2, { mode: 'manual', syncToSelectionColumn: false }) // 仅定位,不选中
api.setIndexFocus(2, { mode: 'manual', syncToSelectionColumn: true }) // 强制同步选中
api.setIndexFocus([]) // 清除定位ClearRowSelectionOptions
clearRowSelection 的可选参数:
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| scope | 'current' \| 'all' | 'all' | all:清空全部选中(含 reserveSelection 离屏选中);current:仅取消当前 display 中的选中 |
api.clearRowSelection() // 清空全部
api.clearRowSelection({ scope: 'all' }) // 同上
api.clearRowSelection({ scope: 'current' }) // 仅清当前可见 display 中的选中SelectionColumnOptions
行选择列配置,通过 selectionColumn prop 传入(rowSelection !== false 时生效)。
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| width | number | 40 | 列宽 px(最小 40) |
| selectAllLabel | string | '全选' | 表头全选 checkbox 的 aria-label |
| rowLabel | (rowIndex) => string | — | 行 checkbox 的 aria-label 工厂 |
| headerAlign / headerValign / align / valign / footerAlign / footerValign | GridHorizontalAlign / GridVerticalAlign | 'center' | 对齐配置 |
RowSelectionConfig
rowSelection 的对象形式:
interface RowSelectionConfig {
mode: 'single' | 'multiple'
/** tree 模式下选中父节点是否级联子孙,默认 true */
groupSelectsChildren?: boolean
}CellSelectionOptions
cellSelection 的对象形式(cellSelection: true 等价 {} 并使用默认子项)。
| 字段 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| suppressMultiRanges | boolean | true | 仅允许单个 range |
| enableColumnSelection | boolean | MagicGrid true / Grid API false | 点击表头选中整列 |
| handleMode | 'off' \| 'fill' \| 'range' | 'off' | Fill / Range 拖拽柄 |
| direction | 'x' \| 'y' \| 'xy' | 'xy' | handleMode: 'fill' 时填充方向 |
| fillStrategy | 'auto' \| 'copy' | 'copy' | 数字递增策略 |
| fillReverseStrategy | 'default' \| 'clear' | 'default' | 反拖缩小行为 |
| setFillValue | `
