news 2026/9/17 1:18:23

Slate v2 访问器与事务公共 API 恢复:getChildren / setChildren / withTransaction / applyBatch 波次计划落地解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Slate v2 访问器与事务公共 API 恢复:getChildren / setChildren / withTransaction / applyBatch 波次计划落地解析

Slate v2 访问器与事务公共 API 恢复:getChildren / setChildren / withTransaction / applyBatch 波次计划落地解析

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

导读

本文围绕 plate 仓库中packages/slate的 Slate v2 演进计划 2026-04-18-slate-v2-slate-accessor-batch-wave-plan.md,系统讲解 Slate v2 如何恢复"访问器 + 快照 + 事务"这一整组最高杠杆的公共 API 接缝:getChildren/setChildrenEditor.getSnapshot/replace/reset/subscribeEditor.withTransaction以及Transforms.applyBatch。读完本文,你将理解这组 API 为什么是"source-first 审计"中被选中的第一波恢复对象、公共接口与运行时接缝分别落在哪些源码文件、测试如何以 TDD 方式拉取草稿(draft)语义、哪些 legacy 语义被显式保留为 cut,以及如何在本地复现验证。

一、背景:为什么这一波聚焦 accessor / transaction 接缝

Slate v2 的恢复工作遵循"source-first"原则:先审计当前收窄(narrowed)后的公共 API 与 legacy Slate 及真实草稿之间的差距,再按杠杆高低分批恢复。此前对Editor.before(...)Editor.after(...)Editor.positions(...)的源码级审计发现,这些运行时文件已经与 legacy 处于"同路径接近"(same-path close)状态,不是最值得投入代码的地方。

与之形成对比的是,accessor / transaction 表面仍然是一处真实存在的已发布收窄(real shipped narrowing)

收窄点现状
getChildren/setChildren当前slate-v2已丢失
快照 / 监听接缝当前slate-v2没有公开的 snapshot / listener 接口
事务接缝当前slate-v2没有公开的 transaction 接口
Transforms.applyBatch(...)当前slate-v2缺失
真实草稿(draft)仍然暴露getChildrensetChildrenEditor.withTransaction(...)Transforms.applyBatch(...)

也就是说,草稿源仍然保留着这组接缝,而当前收窄表面却把它们删掉了。按照该计划的硬性规则:不能让当前收窄表面默认获胜(do not let the current narrowed surface win by default),也不要假装草稿保留了它实际删除的接缝(do not pretend the draft kept seams it actually deleted)。恢复的优先级是:先恢复公共 API 形态(recover the public API shape first),同时保持此前已裁掉的失败语义继续 cut,除非被显式重新打开。

这一方法论在 slate-editor-api.md 中有延续记录:tranche: 3、规则是"先恢复导出的 editor 契约,再修复消费者"(recover exported editor contracts before fixing consumers),并明确"当前收窄不再默认被视为坏的——如果更好的 API 更干净,旧表面是负担,就显式 cut 或降级"。

二、恢复目标全景:八条公共接缝

计划在 Goal 中列出本波次要恢复的完整目标清单:

  • getChildren
  • setChildren
  • Editor.getSnapshot(...)
  • Editor.replace(...)
  • Editor.reset(...)
  • Editor.subscribe(...)
  • Editor.withTransaction(...)
  • Transforms.applyBatch(...)

其中getChildren/setChildren属于访问器(accessor)接缝getSnapshot/subscribe/replace/reset属于快照与外部替换接缝withTransactionapplyBatch属于事务接缝。三者共同构成一个完整的"读(read)→ 事务写(update)→ 一次提交发布(commit publish)"的公共生命周期。在 architecture-contract.md 中,这一形态被概括为:

editor.read(() => { editor.getSelection(); editor.getChildren(); }); editor.update(() => { editor.insertNodes(node); editor.setNodes({ color: "orange" }, { at: [0] }); editor.moveNodes({ at: [3], to: [1] }); });

规则是:editor.update创建事务边界,editor.read读取一致的已提交状态,基本 editor 方法作用于活动事务,提交订阅者(commit subscribers)是主要的提交后边界,而不是用editor.onChange替代作为扩展面。也就是说,即使开发者写的是单操作代码,原生模型也默认是事务性的——这正是withTransactionapplyBatch存在的意义。

三、公共接口层:interfaces/editor.ts 中恢复的签名

计划中"Landed Implementation / Public interface"一节说明,本波次在interfaces/editor.ts中恢复:

  • getChildren
  • setChildren
  • getSnapshot
  • replace
  • reset
  • subscribe
  • withTransaction
  • snapshot 相关类型(snapshot types)

在本仓库中,packages/slate的公共接口类型定义位于 editor-api.ts,其EditorApi<V>类型以三组交叉类型组织:查询类(above/before/after/nodes/positions/string等)、DOM 桥接类(toDOMNode/toSlatePoint/findEventRange等)、扩展类(block/blocks/isAt/some/scrollIntoView等)。访问器与事务方法的恢复即是在这条公共类型链路上新增成员,让Editor.getChildren(editor)Editor.withTransaction(editor, tx => ...)具备显式类型签名。

四、运行时接缝:轻量公共状态 + 可覆写实例方法

计划强调,恢复采用"整包引入草稿的批量(batching)子系统"的激进路线,而是在core/public-state.ts中新增轻量级公共事务 / 访问器状态(lightweight public transaction/accessor state),然后在create-editor.ts中恢复:

  • 公共访问器方法(public accessor methods)
  • 可枚举的children访问器,路由到这些方法(enumerablechildrenaccessor routed through those methods)
  • 快照 / 监听方法(snapshot/listener methods)
  • 事务方法(transaction methods)

在本仓库中,编辑器实例的组装逻辑位于 create-editor.ts:它基于slatecreateSlateEditor()创建底层编辑器,通过多组Object.assignbindFirst绑定各内部实现(deleteBackwardinsertTextsetNodessplitNodeswithoutNormalizing等),并组装editor.apieditor.transformseditor.tf)两组命名空间。访问器 / 快照 / 事务方法的恢复,就是在这一组装点注入对应实现,从而保证:

  • editor.children读操作最终路由到getChildren/setChildren
  • Editor.setChildren(...)路由到可覆写的实例方法(overrideable instance method)。

随后在interfaces/transforms/general.ts中恢复Transforms.applyBatch(...)——计划明确它只是Editor.withTransaction(...)之上的"薄语法糖"(thin sugar)。同时更新core/apply.ts,使其在活动事务内抑制普通的 flush 调度,并在提交时只发布一次(suppress ordinary flush scheduling inside an active transaction and publish once at commit)。这一"事务内不逐操作发布、提交时统一发布"的行为,是整条接缝的性能与一致性关键:一次事务提交对应一次快照发布,而不是一串可观察的部分变更。

这些落地状态在 slate-editor-api.md 中被进一步固化为一套明确的读写层次:

  • 读层次Editor.getOperations(editor)是规范的 operations 读接缝;Editor.withTransaction(editor, tx => ...)暴露草稿式读(tx.childrentx.selectiontx.markstx.operations);tx.apply(op)是第一个显式的事务私有写接缝;applyOperation(editor, op)是内部 helper/transform 写接缝。
  • 写层次Editor.apply(editor, op)成为事务接缝之上的显式公共单操作写入者;editor.update是写边界;直接替换apply/onChange不再是扩展点。
  • 兼容性镜像editor.childreneditor.selectioneditor.markseditor.operations被重新归类为兼容性镜像(compatibility mirror),而非主读取接缝;内部热路径源码(如delete-text.tsget-default-insert-location.ts)改用Editor.getChildren(editor)读取实时草稿状态;slate-reactprovider 回调改读Editor.getChildren/Editor.getOperations/Editor.getLiveSelection
  • 提交次序:提交订阅者在editor.onChange()之前触发,因此onChange更诚实地被理解为"快照存储接缝之上的 legacy 兼容回调"。

五、TDD 姿态:先 RED 拉取草稿语义,再恢复最小接缝

计划明确采用 TDD 执行形态:

  1. 先拉取聚焦的、草稿背书的测试为RED
  2. 保持当前相关测试green
  3. 恢复让这些测试通过所需的最小公共接缝;
  4. 聚焦的 RED 集合变绿后,才进行重构。

优先拉取的草稿背书 RED 切片包括:

  • surface-contract.ts中的访问器路由(accessor routing)
  • transaction-contract.ts中的事务可见性与退出时发布(transaction visibility and publish-on-exit)
  • transaction-contract.ts中的抛错回滚(rollback-on-throw)
  • applyBatch(...)与手写withTransaction(...)的对等性(parity)

同时保持既有测试存活,如packages/slate/test/index.spec.ts

新增的聚焦公共接缝测试集中在test/accessor-transaction.test.ts,覆盖五类行为:

测试点验证内容
children 访问器读取路由经过getChildren/setChildren
Editor.setChildren(...)路由经过可覆写的实例方法
Editor.withTransaction(...)替换状态在事务内可见,退出时只发布一次
Transforms.applyBatch(...)与手写Editor.withTransaction(...)等价,覆盖:重复精确路径set_node、混合 text/selection/node 操作、结构性 insert/move/set 批量
withTransaction(...)抛错对暂存变更执行回滚(rolls back staged changes on throw)

此外,本波次还恢复了 108 个同路径 legacy JSX fixture 文件(packages/slate/test/**),目的是让现有index.spec.ts测试框架"重新诚实"——此前它因 fixture 导入损坏而失败,恢复后不再出现误导性的失败。

在 master-roadmap.md 的 Tranche 3 落地清单中,accessor-transaction.test.ts被列为"当前直接属主且为绿"(present and green)的证明文件之一,与query-contract.tsoperations-contract.tslegacy-editor-nodes-fixtures.tslegacy-interfaces-fixtures.tslegacy-transforms-fixtures.ts并列;同时 roadmap 也给出重要更正——独立的snapshot-contract.ts是宽泛的 oracle 属主,默认不纳入 package-closeout 证明,bun test ./packages/slate/test变绿不代表snapshot-contract.ts独立变绿,这类细节体现了该仓库对证明边界的严谨态度。

六、验证命令

计划给出的完整验证序列如下(路径以计划中的本地 checkout 为准,在本仓库中对应packages/slate包):

# 安装依赖 cd <slate-v2-checkout> && bun install # 构建 slate 包 cd <slate-v2-checkout> && bunx turbo build --filter=./packages/slate # 类型检查 cd <slate-v2-checkout> && bunx turbo typecheck --filter=./packages/slate # 修复 lint cd <slate-v2-checkout> && bun run lint:fix # 运行新增的访问器/事务聚焦测试 cd <slate-v2-checkout>/packages/slate && bun test ./test/accessor-transaction.test.ts # 运行既有完整测试框架,确认无回归 cd <slate-v2-checkout>/packages/slate && bun test ./test/index.spec.ts

对应到本仓库,包级收尾检查在 slate-editor-api.md 中被记录为以下四条全部为绿:bun test ./packages/slate/testbunx turbo build --filter=./packages/slatebunx turbo typecheck --filter=./packages/slatebun run lint:fix(外加bun run lint)。这些命令共同构成了该波次的"诚实回归防线":新增 RED 测试绿、既有测试不破、类型与 lint 干净。

七、显式边界:withBatch 不声称恢复

计划在 "Explicit Boundary" 一节划定了非常清晰的边界:

  • 真实草稿的事务接缝是Editor.withTransaction(...)
  • Editor.withBatch(...)不在真实草稿的 source of truth 中;
  • 因此本波次不声称恢复了withBatch(...)——如果未来想要这个 legacy 兼容名称,应作为一次单独的显式决策处理;
  • 精确的 legacy "抛错时部分提交"(partial-commit-on-throw)批量语义继续保持 cut。

这与 slate-editor-api.md 中的 Tranche 3 规则完全一致:"恢复的公共名称不会自动恢复它们背后的每一个更深层 legacy 语义,显式 cut 要保持显式"(Recovered public names do not automatically recover every deeper legacy semantic behind them. Keep explicit cuts explicit)。也就是说,"名字恢复"与"语义恢复"是两件事,本波次只对名字和契约负责,深层失败语义的取舍留待后续独立决策。

八、结果与下一步

计划在 Result 中给出的结论是:草稿背书的 accessor / transaction / applyBatch 波次已全部为绿(The draft-backed accessor/transaction/applyBatch wave is green)。同时给出一个方法论层面的建议:下一个 tranche-3 动作应当通过重新阅读 ledger 对照这块已落地的接缝来选择,而不是复用该波次之前过时的队列(stale pre-wave queue)。

结合 CHANGELOG.md 中记录的 API 迁移方向,可以看到这组接缝在更广的 API 版图里的位置:getChildren([node, path])迁移为Array.from(NodeApi.children(editor, path)),大量 legacy 函数(getNodeChildrengetFirstChildgetLastChild等)统一收敛到NodeApi.*命名空间,而getSnapshot/subscribe/withTransaction/applyBatch则承担起"快照存储 + 事务写 + 一次提交"这一新的运行时契约。这正是 architecture-contract.md 所强调的:slate必须拥有getSnapshot(editor)subscribe(editor, listener)以及一个显式的外部值 / 快照替换入口,而slate-react不应通过外部观察可变编辑器状态来自造 store,受控模式也不应以"prop 变了跑 effect 再推回 core"来实现。

小结

本波次的价值不在于"多恢复了几个方法名",而在于把 Slate v2 的读 / 写 / 观察模型从"可变对象的直接属性操作"推进到"访问器 + 快照 + 事务 + 一次提交发布"的显式契约:getChildren/setChildren收紧了 children 的读写路径,getSnapshot/subscribe/replace/reset提供了外部 store 式观察与受控替换入口,withTransactionapplyBatch把多操作批处理变成了一等公民,且严格遵循"事务内不逐操作 flush、退出时发布一次、抛错则回滚"的语义。同时,通过withBatch边界与 partial-commit-on-throw 语义的显式 cut,它示范了在 API 恢复工作中如何区分"契约恢复"与"语义恢复",避免把未经验证的 legacy 行为悄悄带回来。

对本仓库感兴趣的读者,可以继续阅读以下路径深入:

  • 计划原文:docs/plans/2026-04-18-slate-v2-slate-accessor-batch-wave-plan.md
  • 编辑器 API 台账:docs/slate-v2/ledgers/slate-editor-api.md
  • Tranche 3 路线图落地状态:docs/slate-v2/master-roadmap.md
  • 架构契约(read/update 生命周期、快照存储、提交订阅者):docs/slate-v2/references/architecture-contract.md
  • 公共接口类型定义:packages/slate/src/interfaces/editor/editor-api.ts
  • 编辑器实例组装:packages/slate/src/create-editor.ts
  • 迁移映射与命名空间收敛:packages/slate/CHANGELOG.md

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 1:17:40

最小二乘法、相关系数与决定系数:回归分析三大指标辨析

做数据分析这行十来年&#xff0c;我发现一个挺有意思的现象&#xff1a;很多人能把最小二乘法、相关系数、决定系数这三个词背得滚瓜烂熟&#xff0c;公式也能默写&#xff0c;可一旦放到真实项目里&#xff0c;就开始乱用。最常见的就是拿一个决定系数去判断两组数据“有没有…

作者头像 李华
网站建设 2026/9/17 1:15:50

C# WebService ASMX实战:VS2019工业级部署全流程

1. 这不是“教科书式”的WebService入门&#xff0c;而是我在产线调试上位机时踩出来的全流程你搜“C# WebService VS2019”&#xff0c;大概率会看到一堆零散截图、半截代码、缺配置步骤的博客&#xff0c;甚至还有把ASMX和WCF混着讲的——我去年在给一家汽车零部件厂做设备数…

作者头像 李华
网站建设 2026/9/17 1:14:47

Flutter+OpenHarmony开发智能家庭相册实践

1. 项目概述&#xff1a;FlutterOpenHarmony家庭相册开发背景家庭相册类应用一直是移动开发领域的经典练手项目&#xff0c;但结合Flutter跨平台框架与OpenHarmony操作系统开发却是个新鲜尝试。这个项目本质上要解决三个核心问题&#xff1a;如何用Flutter高效开发多端一致的UI…

作者头像 李华
网站建设 2026/9/17 1:14:45

云成本巡检进阶:从告警到自动化闭环治理的Mission调度实践

云成本巡检这件事&#xff0c;圈内人有个心照不宣的痛点&#xff1a;告警天天发&#xff0c;账单月月超&#xff0c;但真正动手去治理的人永远只有那么一两个运维。我早先做云上资源治理的时候&#xff0c;也是先搞了一套“成本巡检”&#xff0c;结果跑了两个月&#xff0c;发…

作者头像 李华