使用 JavaScript 创建节点视图
如果你习惯于不使用框架(例如 Vue 或 React),使用这些框架可能会感觉过于复杂。好消息是:你可以在你的节点视图中使用 Vanilla 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') {
// … 触发一个事务,对于文档中的当前位置 …
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*'(这就是我们在上面示例中使用的内容)。