@taocompany/magic-grid 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- [架构与设计](#架构与设计)
|
|
9
9
|
- [快速开始](#快速开始)
|
|
10
10
|
- [数据与性能最佳实践](#数据与性能最佳实践)
|
|
11
|
+
- [Cell Renderer 滚动渲染](#cell-renderer-滚动渲染)
|
|
11
12
|
- [默认配置](#默认配置)
|
|
12
13
|
- [Props](#props)
|
|
13
14
|
- [MagicGrid Props](#magicgrid-props)
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
|
|
41
42
|
| 类别 | 能力 |
|
|
42
43
|
|------|------|
|
|
43
|
-
| **性能** | 行/列双轴虚拟化、DOM 池复用、RAF
|
|
44
|
+
| **性能** | 行/列双轴虚拟化、DOM 池复用、RAF 帧预算分片、Cell Renderer 滚动调度(idle flush · 按行合并 · placeholder-then-vue)、增量数据管线 |
|
|
44
45
|
| **数据** | 排序、列筛选、Quick Filter、事务增量更新(`applyTransaction`)、行 CRUD |
|
|
45
46
|
| **交互** | 单元格/行编辑、校验、行选择、索引列定位、框选与剪贴板 |
|
|
46
47
|
| **布局** | 固定列、列拖拽/调整宽度、列有效性与显隐(`available` / `hidden`)、合并单元格、动态行高、主从展开行 |
|
|
@@ -77,7 +78,7 @@ import '@taocompany/magic-grid/style.css'
|
|
|
77
78
|
|
|
78
79
|
## 架构与设计
|
|
79
80
|
|
|
80
|
-
Magic Grid 采用 **命令式渲染内核 + Vue 薄封装** 的分层架构,对标 AG Grid 社区版 API
|
|
81
|
+
Magic Grid 采用 **命令式渲染内核 + Vue 薄封装** 的分层架构,对标 AG Grid 社区版 API 语义,渲染路径针对百万级行数据做了专门优化。设计文档见仓库 [`docs/`](docs/README.md);Cell Renderer 滚动性能专题见 [`docs/41-cell-renderer-scroll-performance.md`](docs/41-cell-renderer-scroll-performance.md)。
|
|
81
82
|
|
|
82
83
|
### 分层结构
|
|
83
84
|
|
|
@@ -94,7 +95,7 @@ Magic Grid 采用 **命令式渲染内核 + Vue 薄封装** 的分层架构,
|
|
|
94
95
|
- **行虚拟化**:仅渲染视口 + `rowBuffer` 缓冲行;行 DOM 在行池内按 `rowKey` 复用,滚动时更新内容与位置。
|
|
95
96
|
- **列布局**:左固定 / 中心 / 右固定三 lane;中心 lane 随横滚分配列宽。
|
|
96
97
|
- **增量更新**:`applyTransaction`、`setData` 走 RowNode 增量管线;`beginUpdate` / `endUpdate` 可合并多次刷新。
|
|
97
|
-
- **帧预算**:大批量 DOM 写入分片到 `requestAnimationFrame
|
|
98
|
+
- **帧预算**:大批量 DOM 写入分片到 `requestAnimationFrame`(默认 60ms/帧);`cellRenderer` / `#cell-xxx` 插槽走 f1 低优先级队列,可通过 [Cell Renderer 滚动渲染](#cell-renderer-滚动渲染) 调优;测试场景可调用 `flushFrames()` 同步 flush。
|
|
98
99
|
|
|
99
100
|
### 数据管线顺序
|
|
100
101
|
|
|
@@ -189,8 +190,42 @@ const columns: ColumnDef[] = [
|
|
|
189
190
|
### 性能提示
|
|
190
191
|
|
|
191
192
|
- 避免在 `cellRenderer` / `formatter` / `valueGetter` 中创建重量级对象或触发外部副作用;这些函数在滚动时会高频调用。
|
|
193
|
+
- 多列使用 `#cell-{colId}` Vue 插槽时,滚停后可能出现 renderer 列空白拖尾;见下方 [Cell Renderer 滚动渲染](#cell-renderer-滚动渲染) 与 [docs/41-cell-renderer-scroll-performance.md](docs/41-cell-renderer-scroll-performance.md)。
|
|
192
194
|
- 合并单元格(`enableCellSpan`)会启用 `style.top` 行定位并增加 span cache 开销,仅在确有需求时开启。
|
|
193
|
-
- Playground 内置 `getMetrics()` 可观察 `activeDomRowCount`、`lastSetDataMs`
|
|
195
|
+
- Playground 内置 `getMetrics()` 可观察 `activeDomRowCount`、`lastSetDataMs` 等指标;`/phase41` 另提供 `getPendingFrameTaskCount()` / `getPendingRendererTaskCount()`;生产环境可通过 `scroll` / `data-rendered` 事件订阅。
|
|
196
|
+
|
|
197
|
+
### Cell Renderer 滚动渲染
|
|
198
|
+
|
|
199
|
+
带 `cellRenderer` 或 `#cell-{colId}` 插槽的列在滚动时走 **f1 异步队列**(与 prop / formatter 列的同步 `textContent` 路径不同)。多 Vue 组件列场景下,可通过以下 Grid 级 prop 调优(默认均保持优化前行为,需显式开启):
|
|
200
|
+
|
|
201
|
+
| Prop | 类型 | 默认值 | 说明 |
|
|
202
|
+
|------|------|--------|------|
|
|
203
|
+
| `scrollEndFlushMs` | `number` | `0` | 滚动停止 debounce 后 flush RAF;多 Vue 列建议 **100~200** |
|
|
204
|
+
| `frameBudgetMs` | `number` | `60` | 活跃滚动时每帧任务预算(ms) |
|
|
205
|
+
| `scrollEndFrameBudgetMs` | `number` | `-1` | idle flush 帧预算;`-1` = 一次跑完 |
|
|
206
|
+
| `cellRendererDefer` | `'always' \| 'never' \| 'sync-only'` | `'always'` | renderer 是否进入 f1;`sync-only` 仅 Vue renderer 异步 |
|
|
207
|
+
| `deferRowDestroyOnScroll` | `boolean` | `false` | 滚动 active 期间延迟行 destroy + Vue unmount |
|
|
208
|
+
| `rendererFrameBudgetMs` | `number` | `20` | 滚动 active 时为 f1 预留的每帧保底预算(ms);`0` = 与 p1/p2 共享 |
|
|
209
|
+
| `cellRendererPresentation` | `'immediate' \| 'deferred' \| 'placeholder-then-vue'` | `'deferred'` | `placeholder-then-vue`:滚动态先显示 `formattedValue`,idle 后 mount Vue |
|
|
210
|
+
| `rowBuffer` | `number` | `10` | 行虚拟化缓冲;多 Vue 列可降至 **3~5** |
|
|
211
|
+
|
|
212
|
+
列级可选 `cellRendererMount: 'vue' | 'sync'`,配合 `cellRendererDefer: 'sync-only'` 精确控制哪些列走 f1。
|
|
213
|
+
|
|
214
|
+
**多 slot 列业务表推荐配置**(如 ProductOrder):
|
|
215
|
+
|
|
216
|
+
```vue
|
|
217
|
+
<MagicGrid
|
|
218
|
+
:row-buffer="5"
|
|
219
|
+
:scroll-end-flush-ms="150"
|
|
220
|
+
:renderer-frame-budget-ms="20"
|
|
221
|
+
:defer-row-destroy-on-scroll="true"
|
|
222
|
+
cell-renderer-presentation="placeholder-then-vue"
|
|
223
|
+
cell-renderer-defer="always"
|
|
224
|
+
...
|
|
225
|
+
/>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`placeholder-then-vue` 模式下,slot 列需配置可读 `prop` 或 `formatter`,滚动态才有文字兜底。Playground 验收:**`/phase41`**。完整方案见 [docs/41-cell-renderer-scroll-performance.md](docs/41-cell-renderer-scroll-performance.md)。
|
|
194
229
|
|
|
195
230
|
---
|
|
196
231
|
|
|
@@ -236,6 +271,13 @@ const columns: ColumnDef[] = [
|
|
|
236
271
|
| 配置项 | 默认值 | 说明 |
|
|
237
272
|
|--------|--------|------|
|
|
238
273
|
| `rowBuffer` | `10` | 行虚拟化缓冲行数 |
|
|
274
|
+
| `scrollEndFlushMs` | `0` | 滚动停止后 flush RAF(ms);`0` = 关闭 |
|
|
275
|
+
| `frameBudgetMs` | `60` | 活跃滚动帧预算(ms) |
|
|
276
|
+
| `scrollEndFrameBudgetMs` | `-1` | idle flush 帧预算;`-1` = 一次跑完 |
|
|
277
|
+
| `cellRendererDefer` | `'always'` | cellRenderer 调度策略 |
|
|
278
|
+
| `deferRowDestroyOnScroll` | `false` | 滚动 active 期间延迟行 destroy |
|
|
279
|
+
| `rendererFrameBudgetMs` | `20` | 滚动 active 时 f1 每帧保底预算(ms) |
|
|
280
|
+
| `cellRendererPresentation` | `'deferred'` | Vue renderer 呈现策略 |
|
|
239
281
|
| `navigateHeader` | `false` | 不允许焦点进入表头 |
|
|
240
282
|
| `navigateFooter` | `false` | 不允许焦点进入表尾 |
|
|
241
283
|
| `enableHeaderHighlight` | `true` | 框选时表头列高亮 |
|
|
@@ -447,6 +489,13 @@ const columns: ColumnDef[] = [
|
|
|
447
489
|
| Prop | 类型 | 默认值 | 说明 |
|
|
448
490
|
|------|------|--------|------|
|
|
449
491
|
| `rowBuffer` | `number` | `10` | 行虚拟化缓冲行数 |
|
|
492
|
+
| `scrollEndFlushMs` | `number` | `0` | 滚动停止 debounce 后 flush RAF(ms);`0` = 关闭 |
|
|
493
|
+
| `frameBudgetMs` | `number` | `60` | 活跃滚动时每帧任务预算(ms) |
|
|
494
|
+
| `scrollEndFrameBudgetMs` | `number` | `-1` | scroll idle flush 帧预算;`-1` = 一次跑完 |
|
|
495
|
+
| `cellRendererDefer` | `'always' \| 'never' \| 'sync-only'` | `'always'` | cellRenderer 是否进入 f1 异步队列 |
|
|
496
|
+
| `deferRowDestroyOnScroll` | `boolean` | `false` | 滚动 active 期间延迟行 destroy + Vue unmount |
|
|
497
|
+
| `rendererFrameBudgetMs` | `number` | `20` | 滚动 active 时为 f1 预留的每帧保底预算(ms);`0` = 与 p1/p2 共享 |
|
|
498
|
+
| `cellRendererPresentation` | `'immediate' \| 'deferred' \| 'placeholder-then-vue'` | `'deferred'` | Vue renderer 呈现策略;详见 [Cell Renderer 滚动渲染](#cell-renderer-滚动渲染) |
|
|
450
499
|
| `navigateHeader` | `boolean` | `false` | 是否允许键盘/鼠标将焦点导航到表头 |
|
|
451
500
|
| `navigateFooter` | `boolean` | `false` | 是否允许焦点导航到表尾汇总行(需 `showSummary: true`) |
|
|
452
501
|
| `enableHeaderHighlight` | `boolean` | `true` | 表头高亮 |
|
|
@@ -845,6 +894,7 @@ Playground 验收:开发环境 `/phase22` · **T14–T15**(`legacyToken` 列
|
|
|
845
894
|
| `valueGetter` | `(row, value) => unknown` | 取值转换 |
|
|
846
895
|
| `formatter` | `(row, value) => string` | 展示格式化 |
|
|
847
896
|
| `cellRenderer` | `CellRendererFn` | 自定义单元格渲染器(函数;Vue 组件通过 `#cell-{colId}` 插槽) |
|
|
897
|
+
| `cellRendererMount` | `'vue' \| 'sync'` | 列级 renderer 挂载类型;配合 `cellRendererDefer: 'sync-only'` 使用 |
|
|
848
898
|
| `cellEditor` | `CellEditorDef` | 自定义单元格编辑器(函数、内置 `text`/`number`/`checkbox`、或命名引用) |
|
|
849
899
|
| `cellEditorMode` | `'overlay' \| 'inline'` | 编辑器呈现方式;默认 `overlay` |
|
|
850
900
|
| `valueParser` | `(value, params) => unknown` | 提交前解析编辑值 |
|
|
@@ -1697,6 +1747,8 @@ payload 为 `RowExpansionChangedEvent`:
|
|
|
1697
1747
|
| `endUpdate()` | `() => void` | 结束批量更新并 flush 累积变更 |
|
|
1698
1748
|
| `ensureIndexVisible(index, position?)` | `(number, 'top'\|'bottom'\|'middle'?) => void` | 滚动使行下标进入视口;position 默认 `'middle'` |
|
|
1699
1749
|
| `flushFrames()` | `() => void` | 强制 flush 待渲染帧(测试/同步场景) |
|
|
1750
|
+
| `getPendingFrameTaskCount()` | `() => number` | RAF 队列待处理任务总数 |
|
|
1751
|
+
| `getPendingRendererTaskCount()` | `() => number` | f1 队列待处理 cellRenderer 任务数 |
|
|
1700
1752
|
|
|
1701
1753
|
### 类型定义
|
|
1702
1754
|
|
|
@@ -1714,6 +1766,8 @@ interface MagicGridExpose {
|
|
|
1714
1766
|
endUpdate: () => void
|
|
1715
1767
|
ensureIndexVisible: (index: number, position?: 'top' | 'bottom' | 'middle') => void
|
|
1716
1768
|
flushFrames: () => void
|
|
1769
|
+
getPendingFrameTaskCount: () => number
|
|
1770
|
+
getPendingRendererTaskCount: () => number
|
|
1717
1771
|
}
|
|
1718
1772
|
```
|
|
1719
1773
|
|
|
@@ -1815,6 +1869,8 @@ function scrollToRow(index: number) {
|
|
|
1815
1869
|
| `ensureIndexVisible(index, position?)` | position 默认 `'middle'` | `void` | 滚动使行下标进入视口 |
|
|
1816
1870
|
| `getRowNode(id)` | rowId | `RowNode \| undefined` | 按 id 获取行节点 |
|
|
1817
1871
|
| `getMetrics()` | — | `GridMetrics` | 读取渲染与滚动指标 |
|
|
1872
|
+
| `getPendingFrameTaskCount()` | — | `number` | RAF 队列待处理任务总数 |
|
|
1873
|
+
| `getPendingRendererTaskCount()` | — | `number` | f1 队列待处理 cellRenderer 任务数 |
|
|
1818
1874
|
| `beginUpdate()` / `endUpdate()` | — | `void` | 批量更新(与 applyTransaction 配对) |
|
|
1819
1875
|
| `scrollTo(scrollTop, scrollLeft?)` | px | `void` | 编程式滚动 |
|
|
1820
1876
|
|
|
@@ -2827,9 +2883,10 @@ pnpm typecheck # Vue + TS 类型检查
|
|
|
2827
2883
|
| 路由 | 主题 |
|
|
2828
2884
|
|------|------|
|
|
2829
2885
|
| `/phase2` – `/phase27` | 各 Phase 功能演示与验收用例 |
|
|
2886
|
+
| `/phase41` | Cell Renderer 滚动性能(5000 行 × 多 `#cell-xxx` · pending 指标 · 调参) |
|
|
2830
2887
|
| `/glossary` | 术语表 |
|
|
2831
2888
|
|
|
2832
|
-
典型入口:`pnpm dev` 后访问控制台输出的本地 URL,从侧边栏切换 Phase。例如列显隐验收 **`/phase22`**(T14–T15 · `available`
|
|
2889
|
+
典型入口:`pnpm dev` 后访问控制台输出的本地 URL,从侧边栏切换 Phase。例如列显隐验收 **`/phase22`**(T14–T15 · `available` 列切换);多 Vue slot 列滚停拖尾验收 **`/phase41`**。
|
|
2833
2890
|
|
|
2834
2891
|
Playground 源码位于仓库 `playground/` 目录;自定义 Vue 编辑器示例见 `playground/components/editors/`(Element Plus 集成参考)。
|
|
2835
2892
|
|