tiptap 使用 Vue 渲染视图节点
引言
如果你习惯使用 Vue 工作,那么用原生 JavaScript 可能会感觉复杂。好消息是:你也可以在节点视图中使用常规的 Vue 组件。只需要了解一些基本知识,接下来我们会逐一讲解。
渲染 Vue 组件
要在编辑器中渲染 Vue 组件,你需要做以下步骤:
- 创建节点扩展
- 创建 Vue 组件
- 将该组件传递给提供的
VueNodeViewRenderer
- 通过
addNodeView()
注册它 - 配置 Tiptap 使用新的节点扩展
你的节点扩展可能看起来像这样:
import { Node } from "@tiptap/core";
import { VueNodeViewRenderer } from "@tiptap/vue-2";
import Component from "./Component.vue";
export default Node.create({
// 配置...
addNodeView() {
return VueNodeViewRenderer(Component);
},
});
为了让这个工作,需要一点魔法。别担心,我们提供了一个启动器组件,你可以轻松开始使用。别忘了在自定义 Vue 组件中添加它,如下所示:
<template>
<node-view-wrapper> Vue组件 </node-view-wrapper>
</template>
明白了吗?现在让我们实际操作一下。你可以复制下面的示例开始:
https://embed.tiptap.dev/preview/GuideNodeViews/VueComponent
然而,这个组件还不与编辑器交互。现在该连接起来了。
访问节点属性
在节点扩展中使用的 VueNodeViewRenderer
会将一些非常有用的属性传给你的自定义 Vue 组件。其中一个是 node
属性。在组件中添加这个片段以便直接访问节点:
props: {
node: {
type: Object,
required: true,
},
},
这样你就可以在 Vue 组件中访问节点属性了。假设你在扩展中添加了一个名为 count
的属性(如上例所示),你可以这样访问:
this.node.attrs.count;
更新节点属性
借助传给组件的 updateAttributes
属性,你甚至可以在节点中更新属性。在组件中添加以下片段:
props: {
updateAttributes: {
type: Function,
required: true,
},
},
然后将更新后的属性对象传递给函数:
this.updateAttributes({
count: this.node.attrs.count + 1,
});
而且,这一切都是响应式的。是不是很无缝的通信呢?
添加可编辑内容
还有一个名为 NodeViewContent
的组件,可以帮助你在节点视图中添加可编辑内容。看个例子:
<template>
<node-view-wrapper class="dom">
<node-view-content class="content-dom" />
</node-view-wrapper>
</template>
<script>
import { NodeViewWrapper, NodeViewContent } from "@tiptap/vue-2";
export default {
components: {
NodeViewWrapper,
NodeViewContent,
},
};
</script>
你不需要添加这些 class
属性,可以删除或使用其他类名。尝试下面的例子:
https://embed.tiptap.dev/preview/GuideNodeViews/VueComponentContent
请记住,这部分内容由 Tiptap 渲染。这意味着你需要指定允许什么样的内容,例如在节点扩展中使用 content: 'inline*'
(如上例所示)。
NodeViewWrapper
和 NodeViewContent
组件渲染 <div>
HTML 标签(对于行内节点是 <span>
),但你可以更改这个。例如,<node-view-content as="p">
应该渲染一个段落。不过有一个限制:这个标签在运行时不能改变。
所有可用的属性
对于高级用法,我们还会向组件传递更多属性。
editor
编辑器实例。
node
访问当前节点。
decorations
装饰数组。
selected
当当前节点视图有 NodeSelection
时,设置为 true
。
extension
访问节点扩展,例如获取选项。
getPos()
获取当前节点的文档位置。
updateAttributes()
更新当前节点的属性。
deleteNode()
删除当前节点。
以下是你可以期待的所有属性完整列表:
<template>
<node-view-wrapper />
</template>
<script>
import { NodeViewWrapper } from "@tiptap/vue-2";
export default {
components: {
NodeViewWrapper,
},
props: {
// 编辑器实例
editor: {
type: Object,
},
// 当前节点
node: {
type: Object,
},
// 装饰数组
decorations: {
type: Array,
},
// 当前节点视图有`NodeSelection`时为`true`
selected: {
type: Boolean,
},
// 节点扩展的访问,例如获取选项
extension: {
type: Object,
},
// 获取当前节点的文档位置
getPos: {
type: Function,
},
// 更新当前节点的属性
updateAttributes: {
type: Function,
},
// 删除当前节点
deleteNode: {
type: Function,
},
},
};
</script>
如果你只想拥有所有(并带有 TypeScript 支持),你可以导入所有的属性:
// Vue 3
import { defineComponent } from 'vue'
import { nodeViewProps } from '@tiptap/vue-3'
export default defineComponent({
props: nodeViewProps,
})
// Vue 2
import Vue from 'vue'
import { nodeViewProps } from '@tiptap/vue-2'
export default Vue.extend({
props: nodeViewProps,
})
拖放
要使节点视图可拖动,将扩展的 draggable
属性设置为 true
,并在作为拖动处理程序的 DOM 元素上添加 data-drag-handle
属性。