tiptap 使用 React 渲染视图节点
引言
如果你习惯于使用 React 工作,那么使用纯 JavaScript 可能会感觉复杂。好消息是:你也可以在 Node 视图中使用普通的 React 组件。只需要了解一些基本知识,接下来我们将逐一讲解。
渲染 React 组件
要在编辑器中渲染 React 组件,你需要做以下步骤:
- 创建自定义扩展
- 创建 React 组件
- 将组件传递给提供的
ReactNodeViewRenderer
- 使用
addNodeView()
注册它 - 配置 Tiptap 使用新的 Node 扩展
这是你的 Node 扩展可能的样子:
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>
明白了吗?现在让我们实际操作一下。请复制下面的示例开始:
https://embed.tiptap.dev/preview/GuideNodeViews/ReactComponent
这个组件还不与编辑器交互。现在是时候连接它们了。
访问节点属性
在 Node 扩展中使用的 ReactNodeViewRenderer
会将一些非常有用的属性传递给你的自定义 React 组件。其中一个是 node
属性。假设你在扩展中添加了一个名为 count
的属性(如上例所示),你可以像这样访问它:
props.node.attrs.count;
更新节点属性
借助传递给组件的 updateAttributes
属性,甚至可以在组件内部更新节点属性。将更新后的属性对象传递给 updateAttributes
属性:
export default (props) => {
const increase = () => {
props.updateAttributes({
count: props.node.attrs.count + 1,
});
};
// ...
};
是的,这一切都是实时的。通信相当顺畅,不是吗?
添加可编辑内容
还有一个名为 NodeViewContent
的组件,可以帮助你向 Node 视图添加可编辑内容。看个例子:
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
属性,可以移除或传入其他类名。尝试下面的例子:
https://embed.tiptap.dev/preview/GuideNodeViews/ReactComponentContent
请记住,这里的可编辑内容由 Tiptap 渲染。这意味着你需要告诉允许什么样的内容,例如在扩展中使用 content: 'inline*'
(如上面示例所示)。
NodeViewWrapper
和 NodeViewContent
组件默认渲染 <div>
标签(对于行内节点是<span>
),但你可以更改。例如,<NodeViewContent as="p">
应该渲染一个段落。但有一个限制:这个标签在运行时不能改变。
更改 Node 视图的默认内容标签
ReactNodeViewRenderer
默认会在渲染的 Node 视图中包裹一个 div
。如果你想更改这个节点的类型,可以在 ReactNodeViewRenderer
选项中设置 contentDOMElementTag
:
// 这将把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" });
},
});
所有可用属性
这是你能期待的所有属性列表:
editor
编辑器实例
node
当前节点
decorations
装饰数组
selected
当当前 Node 视图有 NodeSelection
时为 true
extension
访问节点扩展,例如获取选项
getPos()
获取当前节点的文档位置
updateAttributes()
更新当前节点的属性
deleteNode()
删除当前节点
拖放
要使 Node 视图可拖动,将 draggable
设置为 true
在扩展中,并为希望作为拖动处理的 DOM 元素添加 data-drag-handle
属性。