探索 Tiptap V3 的最新功能

使用 React 的节点视图

如果您习惯于使用 React 工作,使用普通 JavaScript 可能会感觉复杂。好消息是:您也可以在节点视图中使用常规的 React 组件。您只需知道一点小知识,让我们逐步来看。

渲染 React 组件

要在编辑器中渲染 React 组件,您需要执行以下操作:

  1. 创建一个节点扩展
  2. 创建一个 React 组件
  3. 将该组件传递给提供的 ReactNodeViewRenderer
  4. 使用 addNodeView() 注册
  5. 配置 Tiptap 使用您的新节点扩展

您的节点扩展可能看起来像这样:

import { Node } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import Component from './Component.jsx'

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

  addNodeView() {
    return ReactNodeViewRenderer(Component)
  },
})

要使其正常工作需要一点魔法。但不要担心,我们提供了一个可以帮助您轻松入门的包装组件。不要忘记将其添加到您的自定义 React 组件中,如下所示:

<NodeViewWrapper className="react-component">React 组件</NodeViewWrapper>

明白了吗?让我们看看实际效果。请随意复制以下示例开始吧。

不过,该组件并不会与编辑器交互。是时候将其连接起来了。

访问节点属性

您在节点扩展中使用的 ReactNodeViewRenderer,向您的自定义 React 组件传递了一些非常有用的 props。其中之一是 node prop。假设您已向节点扩展添加了名为 count 的属性(就像我们在上面的示例中做的那样),您可以这样访问它:

props.node.attrs.count

更新节点属性

您甚至可以通过节点更新节点属性,借助传递给您的组件的 updateAttributes prop。将更新后的属性对象传递给 updateAttributes prop:

export default (props) => {
  const increase = () => {
    props.updateAttributes({
      count: props.node.attrs.count + 1,
    })
  }

  // …
}

是的,这一切都是响应式的。这是非常无缝的通信,不是吗?

添加可编辑内容

还有一个名为 NodeViewContent 的组件,可以帮助您向节点视图添加可编辑内容。以下是一个示例:

import React from 'react'
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react'

export default () => {
  return (
    <NodeViewWrapper className="react-component">
      <span className="label" contentEditable={false}>
        React 组件
      </span>

      <NodeViewContent className="content" />
    </NodeViewWrapper>
  )
}

您不需要添加这些 className 属性,可以随意删除它们或传递其他类名。在以下示例中试试:

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

NodeViewWrapperNodeViewContent 组件渲染一个 <div> HTML 标签(对于行内节点则是 <span>),但您可以更改它。例如 <NodeViewContent as="p"> 应该渲染一个段落。不过有一个限制:该标签在运行时必须不可更改。

更改节点视图的默认内容标签

默认情况下,ReactNodeViewRenderer 渲染的节点视图将始终包含一个包裹的 div。如果您想更改此节点的类型,可以将 contentDOMElementTag 添加到 ReactNodeViewRenderer 选项:

// 这将把 div 转变为 header 标签
return ReactNodeViewRenderer(Component, { contentDOMElementTag: 'header' })

更改包裹的 DOM 元素

要更改包裹 DOM 元素的标签,您可以在 ReactNodeViewRenderer 函数上使用 contentDOMElementTag 选项来更改默认标签名称。

import { Node } from '@tiptap/core'
import { ReactNodeViewRenderer } from '@tiptap/react'
import Component from './Component.jsx'

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

  addNodeView() {
    return ReactNodeViewRenderer(Component, { contentDOMElementTag: 'main' })
  },
})

所有可用的 props

以下是您可以期待的 props 完整列表:

Prop描述
editor编辑器实例
node当前节点
decorations装饰数组
selected当当前节点视图有 NodeSelection 时为 true
extension访问节点扩展,例如获取选项
getPos()获取当前节点的文档位置
updateAttributes()更新当前节点的属性
deleteNode()删除当前节点

拖动

要使您的节点视图可拖动,请在扩展中设置 draggable: true,并将 data-drag-handle 添加到应该作为拖动句柄的 DOM 元素。