tiptap 使用 JavaScript 渲染节点视图
引言
如果你习惯于不使用 Vue 或 React,但又想在你的 Node 视图中使用原生 JavaScript,那其实并不复杂。只需要了解一些基本知识,我们一步步来。
用 JavaScript 渲染节点视图
要在编辑器中渲染节点视图,你需要做以下步骤:
- 创建一个节点扩展
- 通过
addNodeView()
注册新的节点视图 - 编写渲染函数
- 配置 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') {
// ... 对当前文档位置发送事务,更新`count`属性 ...
view.dispatch(view.state.tr.setNodeMarkup(getPos(), undefined, {
count: node.attrs.count + 1,
}))
// ... 并将焦点重新设置到编辑器。
editor.commands.focus()
}
})
// ...
}
}
这看起来可能有点复杂?如果你项目中已经使用了 React 或 Vue,考虑使用它们,会更轻松些。
添加可编辑内容
为了在节点视图中添加可编辑内容,你需要提供一个 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*'
(如上面的示例所示)。