Skip to content
目录

性能优化:Selector 与 Chunking

1. Slate 的性能瓶颈通常在哪

  1. 每次输入触发大范围 React 重渲染
  2. 大文档结构更新导致节点树遍历和 key 映射成本高
  3. 选区变化导致高频状态刷新

Slate 的策略是两层优化:

  • 订阅粒度优化(selector)
  • 渲染树分块(chunking)

2. useSlateSelector:避免“每次按键全组件刷新”

文件:packages/slate-react/src/hooks/use-slate-selector.tsx

关键点:

  • redux 风格 selector + equalityFn
  • 只在 selector 结果变化时更新组件
  • 支持 deferred:延迟到 Editable 渲染后再执行 selector

deferred 的设计非常实用:避免 selector 内部 findPath 读到旧路径。

源码注释(节选):

ts
/**
 * If true, defer calling the selector function until after `Editable` has
 * finished rendering. This ensures that `ReactEditor.findPath` won't return
 * an outdated path if called inside the selector.
 */

测试依据:

  • packages/slate-react/test/use-slate-selector.spec.tsx

3. Chunking:把大 children 列表拆成块

主要文件:

  • components/chunk-tree.tsx
  • chunking/get-chunk-tree-for-node.ts
  • chunking/reconcile-children.ts
  • chunking/types.ts

核心思路:

  • 对大 children 构建 chunk tree,而不是平铺渲染
  • React.memo + modifiedChunks 精准控制重渲染块
  • movedNodeKeys 特判 move_node,避免把 move 误判成大量 insert/remove

这是 Slate 近年比较“工程化”的性能演进点。


4. withReact 如何和 chunking 联动

文件:packages/slate-react/src/plugin/with-react.ts

  • 默认 getChunkSize = () => null
  • 当业务覆写 getChunkSize 后启用 chunking
  • move_node 时,把被移动节点 key 标记进 chunkTree.movedNodeKeys

这一步是 reconcile 正确识别“移动”而非“删除+插入”的关键。


5. 测试覆盖强度

packages/slate-react/test/chunking.spec.ts 的价值很高:

  • 初始 chunk 形态
  • 插入/删除/移动/更新后的树形对齐
  • 大量随机操作一致性测试(随机种子可复现)

这类测试说明 chunking 不是 UI 小优化,而是核心渲染基础设施。


6. 使用建议(业务侧)

  1. 普通文档先用 selector 优化,不要过早 chunking
  2. 超长文档(例如数百 block)再评估启用 getChunkSize
  3. selector 返回对象时务必配 equalityFn,避免伪变化
  4. 避免在高频路径里调用昂贵 Editor.nodes 全量扫描

7. 回答模板

Slate 的性能不是靠单点技巧,而是“订阅粒度 + 渲染结构”双优化。
useSlateSelector 解决不必要订阅更新,chunking 解决长列表渲染成本。
尤其 move_node 场景通过 movedNodeKeys 纠正 reconcile 语义,这是一个典型的工程级性能设计。

MIT License.