跳到正文
QuireKit
Core 开发文档
Alpha · API 持续演进

编写交互式 NodeView

给持久计数器节点增加一个按钮,理解显示、位置、事务和清理的关系。

Node 定义保存什么,NodeView 定义编辑时如何交互。本章使用 DOM 后端,给一个计数器块增加“+1”按钮。Canvas/SVG 的布局与选区适配见内容扩展教程,不能直接复用这里的 DOM 按钮作为画布节点。

1. 把 count 放进正文

docsCounter 是不包含可编辑子内容的块级 atom,count 是默认值为 0 的属性。JSON 保存计数;renderHTML() 输出一个静态元素,不输出编辑按钮。

core/node-view/counter.tsts

安装 createCounterNode(),再插入 { type: 'docsCounter', attrs: { count: 0 } }。atom: true 表示正文把它视为一个整体,不意味着所有读取、导出、布局能力都自动存在。本例没有实现 Markdown、DOCX 或 AI 合同。

2. 点击时读取最新位置与节点

用户在计数器前输入内容后,节点位置会改变。按钮每次点击调用 getPos(),再调用 incrementDocsCounter(position)。命令从当前事务的 tr.doc 读取节点与 count,验证类型、数字范围和只读状态,然后修改属性。

不要闭包首次挂载时的数字,点击时再写 initialCount + 1;也不要保存首次 getPos() 的结果。dispatch 不存在时只检查可执行性,所以 can().incrementDocsCounter(position) 不会增加计数。

3. 让 View 跟随正文更新

core/node-view/view.tsts

update(next) 接收新的不可变节点,同类型就更新按钮并返回 true;不同类型返回 false,由视图重建。contentEditable=false 表示按钮不是正文输入区域,stopEvent 把按钮事件交给控件。

这个 atom 没有 contentDOM,自身按钮变化可以由 ignoreMutation() 忽略。包含可编辑子内容的 NodeView 需要提供 contentDOM,并让正文内的输入与选区变化交给编辑器;不能照搬这里“一律忽略”的规则。destroy() 移除本次创建的监听。

4. 试用与核对保存结果

正在准备示例…

点击两次 +1,计数应为 2;撤销后应为 0 或前一历史分组的值。下载 JSON 查看 attrs.count,里面不应保存按钮 DOM。再在计数器前插入段落,确认点击仍修改同一个节点。完整挂载组件在预览的源码页签中,节点和 View 可以分别查阅。

只读检查属于本例的写入命令,避免按钮在只读时仍修改正文。更复杂的控件还要处理键盘可达性、焦点恢复、选中态,以及与外部数据请求的取消和失败。

QuireKitQuireKit · Core、插件与 Classic 文档