项目

tiptap 可交互节点视图

引言

节点视图就像切片面包一样出色,至少对于喜欢定制(和面包)的人来说是这样。通过节点视图,您可以在编辑器中添加交互式的节点。这几乎可以是任何东西。如果你能用 JavaScript 写出来,你就可以在你的编辑器中使用它。

节点视图极大地提升了编辑器内的用户体验,但也可以用于只读的 Tiptap 实例中。它们与 HTML 输出设计上无关,因此你完全控制着编辑器内的体验和输出。

不同类型的节点视图

根据你想要构建的内容,节点视图的工作方式略有不同,它们可能具有特定的能力,但也可能存在一些陷阱。主要问题是:你希望自定义节点看起来像什么?

可编辑文本

是的,节点视图可以包含可编辑文本,就像常规节点一样。这很简单。光标的行为会像你期望的常规节点那样。现有的命令与这些节点配合得很好。

<div class="Prosemirror" contenteditable="true">
  <p>text</p>
  <node-view>text</node-view>
  <p>text</p>
</div>

这就是TaskItem节点的工作原理。

非可编辑文本

节点也可以有不可编辑的文本。光标无法跳入其中,而且你也不想让它这么做。

Tiptap 默认为这些添加了contenteditable="false"属性。

<div class="Prosemirror" contenteditable="true">
  <p>text</p>
  <node-view contenteditable="false">text</node-view>
  <p>text</p>
</div>

你可以这样渲染提及,它们不应该可编辑。用户可以添加或删除它们,但不能删除单个字符。

Statamic 在他们的 Bard 编辑器中使用这种方式,它在 Tiptap 中渲染复杂的模块,这些模块可以有自己的文本输入。

混合内容

你甚至可以混合非可编辑和可编辑的文本。这对于构建复杂内容非常有用,同时仍然可以在可编辑内容中使用粗体、斜体等标记。

但是,如果节点视图中有其他不可编辑文本元素,光标可能会跳到那里。你可以通过手动为节点视图中的特定部分添加 contenteditable="false" 来改进这一点。

<div class="Prosemirror" contenteditable="true">
  <p>text</p>
  <node-view>
    <div contenteditable="false">非可编辑文本</div>
    <div>可编辑文本</div>
  </node-view>
  <p>text</p>
</div>

格式化

但是,当你 访问编辑器内容 时会发生什么呢?如果你使用的是 HTML,你需要告诉 Tiptap 如何序列化你的节点。

编辑器不会导出渲染后的 JavaScript 节点,而且在很多情况下,你也不希望这样做。

假设你有一个节点视图,让用户添加视频播放器并配置外观(自动播放、控制等)。你希望界面在编辑器中完成这些操作,而不是在编辑器的输出中。编辑器的输出可能只包含视频播放器。

我知道,我知道,这并不简单。请记住,你完全控制着编辑器内的渲染和输出。

警告 如果存储 JSON 呢?
这不适用于 JSON。在 JSON 中,所有内容都作为对象存储。不需要配置从 JSON 到 HTML 的 “转换” 。

渲染 HTML

好的,你已经设置了带有交互式节点视图的节点,现在你想控制输出。即使你的节点视图很复杂,渲染后的 HTML 也可以很简单:

renderHTML({ HTMLAttributes }) {
  return ['my-custom-node', mergeAttributes(HTMLAttributes)]
},

确保它是可区分的,以便更容易从 HTML 中恢复内容。如果你只需要类似 <div> 的通用标记,请考虑添加一个 data-type="my-custom-node" 属性。

解析 HTML

恢复内容时也是如此。你可以配置你期望的标记,这可以与节点视图的标记完全无关。它只需要包含你想恢复的所有信息。

如果注册了属性,属性会自动恢复 [1]。

// 输入: <my-custom-node count="1"></my-custom-node>

parseHTML() {
  return [{
    tag: 'my-custom-node',
  }]
},

渲染 JavaScript/Vue/React

但如果想渲染实际的 JavaScript/Vue/React 代码呢?考虑使用 Tiptap 来渲染输出。只需将编辑器设置为 editable: false ,没人会注意到你在用一个编辑器来渲染内容。:-)

[1]: 如果你通过 addAttributes 注册了属性,它们会自动恢复。

在本文档中