探索 Tiptap V3 的最新功能

使用 JavaScript 创建节点视图

如果你习惯于不使用框架(例如 Vue 或 React),使用这些框架可能会感觉过于复杂。好消息是:你可以在你的节点视图中使用 Vanilla JavaScript。你只需了解一些基本知识,接下来我们就一个一个来看。

使用 JavaScript 渲染节点视图

要在编辑器中渲染节点视图,你需要执行以下步骤:

  1. 创建节点扩展
  2. 使用 addNodeView() 注册一个新的节点视图
  3. 编写你的渲染函数
  4. 配置 Tiptap 使用你的新节点扩展

以下是你的节点扩展的样子:

import { Node } from '@tiptap/core'

export default Node.create({
  // 配置 …

  addNodeView() {
    return ({ editor, node, getPos, HTMLAttributes, decorations, extension }) => {
      const dom = document.createElement('div')

      dom.innerHTML = '你好,我是一个节点视图!'

      return {
        dom,
      }
    }
  },
})

明白了吗?让我们看看这个如何运作。你可以随意复制下面的示例开始使用。

这个节点视图甚至可以与编辑器进行交互。现在是时候看看它是如何建立联系的。

访问节点属性

编辑器会将一些有用的信息传递给你的渲染函数。其中一个是 node 属性。这个属性使你能够访问节点视图中的节点属性。假设你为你的节点扩展 添加了一个属性 名称为 count。你可以像这样访问该属性:

addNodeView() {
  return ({ node }) => {
    console.log(node.attrs.count)

    // …
  }
}

更新节点属性

你甚至可以在节点视图中更新节点属性,利用传递给渲染函数的 getPos 属性。通过一个包含更新后属性的对象来触发新的事务:

addNodeView() {
  return ({ editor, node, getPos }) => {
    const { view } = editor

    // 创建一个按钮 …
    const button = document.createElement('button')
    button.innerHTML = `这个按钮已经被点击了 ${node.attrs.count} 次。`

    // … 当它被点击时 …
    button.addEventListener('click', () => {
      if (typeof getPos === 'function') {
        // … 触发一个事务,对于文档中的当前位置 …
        view.dispatch(view.state.tr.setNodeMarkup(getPos(), undefined, {
          count: node.attrs.count + 1,
        }))

        // … 然后把焦点设置回编辑器。
        editor.commands.focus()
      }
    })

    // …
  }
}

这似乎有点复杂吗?如果你在项目中已经使用了 ReactVue,可以考虑使用它们。使用这些框架会稍微简单一些。

添加可编辑内容

要向你的节点视图添加可编辑内容,你需要传递一个 contentDOM,这是用于内容的容器元素。以下是一个包含非可编辑和可编辑文本内容的节点视图的简化示例:

// 创建节点视图的容器
const dom = document.createElement('div')

// 给其他包含文本的元素设置 `contentEditable = false`
const label = document.createElement('span')
label.innerHTML = '节点视图'
label.contentEditable = false

// 创建内容的容器
const content = document.createElement('div')

// 将所有元素附加到节点视图容器
dom.append(label, content)

return {
  // 传递节点视图容器 …
  dom,
  // … 以及内容容器:
  contentDOM: content,
}

明白了吗?你可以随意做任何你喜欢的事情,只要你返回一个节点视图的容器和另一个内容的容器。以下是上面示例的实际应用:

请记住,这些内容是由 Tiptap 渲染的。这意味着你需要指明允许什么样的内容,比如在你的节点扩展中使用 content: 'inline*'(这就是我们在上面示例中使用的内容)。