Skip to content
目录

高级特性案例:Suggestion / Table / NodeView

1. Suggestion:输入法、光标和异步数据的交叉地带

核心文件:packages/suggestion/src/suggestion.ts

1.1 插件状态机

Suggestion 插件内部维护:

  • active
  • range
  • query/text
  • decorationId
  • composing

状态由 transaction apply 驱动,view update 决定 onStart/onUpdate/onExit 触发时机。

1.2 输入法兼容(IME)

代码中显式处理 composing 场景,并在注释中引用历史问题(issue #1449)。
本质是:IME 组合输入时 selection 与文本更新时序不同于英文输入。

1.3 协同友好的 shouldShow

v3.15 增加 shouldShow(并传入 transaction),可过滤“远端事务触发本地弹层”的误触发。

证据:

  • Changelog v3.15.1
  • 单测:packages/suggestion/src/__tests__/suggestion.test.ts

1.4 安全退出机制

提供 exitSuggestion(view, pluginKey),通过 metadata-only transaction 退出,不改文档。
这是避免 decoration 映射错乱的关键策略。

源码片段(packages/suggestion/src/suggestion.ts):

ts
export function exitSuggestion(view: EditorView, pluginKeyRef: PluginKey = SuggestionPluginKey) {
  const tr = view.state.tr.setMeta(pluginKeyRef, { exit: true })
  view.dispatch(tr)
}

2. Table:复用 PM tables,同时暴露更友好的业务 API

核心文件:packages/extension-table/src/table/table.ts

2.1 设计策略

  • 底层命令基本代理 @tiptap/pm/tables(addRow/deleteColumn/mergeCells...)。
  • 上层补充:
    • insertTable
    • mergeOrSplit
    • setCellSelection
    • markdown parse/render 适配

2.2 编辑态与只读态表现差异

  • resizable && editor.isEditable 时才注入 columnResizing
  • 新增 renderWrapper 选项,控制只读模式是否也保留 wrapper(见 changelog v3.9.1)。

2.3 键盘行为工程化

Tab 在末单元格时自动新增行并跳转。
这类“接近产品期望”的行为不是 PM 原生提供,而是扩展层封装出的高阶语义。

3. NodeView:可视化自定义的桥

3.1 Core NodeView 基类

位置:packages/core/src/NodeView.ts

提供:

  • drag handle 处理
  • stopEvent/ignoreMutation 细粒度控制
  • iOS/Android 输入边界兼容逻辑
  • updateAttributes/deleteNode 公共能力

3.2 ReactNodeViewRenderer 适配层

位置:packages/react/src/ReactNodeViewRenderer.tsx

关键点:

  • 用 ReactRenderer 挂载组件并回填 contentDOMElement
  • selection 更新走 requestAnimationFrame 节流。
  • 支持 update 回调做自定义 diff,减少不必要 re-render。
  • 强约束 NodeViewWrapper(避免结构不合法)。

3.3 ReactRenderer 的生命周期细节

位置:packages/react/src/ReactRenderer.tsx

  • editor 已初始化时 flushSync 保证与 PM 渲染节奏一致。
  • 未初始化用 queueMicrotask 延后,且带 destroyed 守卫。
  • destroy 时移除 portal 与 DOM 节点,避免泄漏。

这是把“外部渲染器”嵌入 PM NodeView 生命周期的经典实现。

4. 可讲的统一结论

Suggestion、Table、NodeView 三类高级特性共同体现:

  1. 业务语义封装在扩展层,不污染内核。
  2. 复杂时序通过 transaction + plugin state 管理。
  3. 对浏览器兼容与框架生命周期边界有大量工程化兜底。

MIT License.