拖拽句柄 Vue 扩展

版本下载量

您是否曾希望在基于 Vue 的编辑器中拖动节点?好吧,我们也有这个想法——所以这就是为此而创建的扩展。

DragHandleVue 组件使您能够轻松地在编辑器中拖动节点。您可以定义自定义渲染函数、位置等。
它实质上将 DragHandle 扩展包装在 Vue 组件中,并会自动与编辑器注册/注销扩展。

安装

npm install @tiptap/extension-drag-handle-vue-3 @tiptap/extension-drag-handle @tiptap/extension-node-range @tiptap/extension-collaboration @tiptap/y-tiptap yjs y-protocols

Vue 2 与 Vue 3 的区别

拖拽句柄扩展提供两个版本。请确保根据您的 Vue 版本安装正确的版本。分别是 @tiptap/extension-drag-handle-vue-2@tiptap/extension-drag-handle-vue-3

属性

所有属性遵循与 DragHandle 扩展相同的结构。

children

应显示在拖拽句柄内的内容。

<drag-handle>
  <div>拖拽我!</div>
</drag-handle>

computePositionConfig

拖拽句柄位置计算的配置,使用 floating-ui/dom 包。您可以传入在 floating-ui 文档 中列出的任意选项。

默认值: { placement: 'left-start', strategy: 'absolute' }

<drag-handle :compute-position-config="{ placement: 'left', strategy: 'fixed' }">
  <div>拖拽我!</div>
</drag-handle>

onNodeChange

当节点被悬停时返回节点或者 null。您可以用它来高亮当前悬停的节点。

默认值: undefined

<template>
  <drag-handle @nodeChange="handleNodeChange">
    <div>拖拽我!</div>
  </drag-handle>
</template>

<script>
import { ref } from 'vue'
import { DragHandle } from '@tiptap/extension-drag-handle-vue-3'

export default {
  components: {
    DragHandle,
  },
  setup() {
    const selectedNode = ref(null)

    const handleNodeChange = ({ node, editor, pos }) => {
      selectedNode.value = node
      // 对节点执行某些操作
    }

    return {
      selectedNode,
      handleNodeChange,
    }
  },
}
</script>

getReferencedVirtualElement

返回拖拽句柄虚拟元素的函数。当菜单需要相对于特定 DOM 元素定位时,这很有用。

默认值: undefined

<template>
  <drag-handle :get-referenced-virtual-element="getVirtualElement">
    <div>拖拽我!</div>
  </drag-handle>
</template>

<script>
export default {
  setup() {
    const getVirtualElement = () => {
      // 返回用于自定义定位的虚拟元素
      return null
    }

    return {
      getVirtualElement,
    }
  },
}
</script>

locked

锁定拖拽句柄的位置和可见性。如果拖拽句柄原本可见,则保持可见直到解除锁定;如果原本隐藏,则保持隐藏直到解除锁定。

默认值: false

<drag-handle :locked="true">
  <div>拖拽我!</div>
</drag-handle>

pluginKey

编辑器中用于存储插件的键。当您在同一编辑器中使用多个拖拽句柄时,该属性非常有用。

默认值: undefined

<drag-handle pluginKey="myCustomDragHandle">
  <div>拖拽我!</div>
</drag-handle>

nested

启用嵌套内容(如列表项、引用块和其他嵌套结构)的拖拽句柄功能。

启用后,拖拽句柄会出现在嵌套块,而不仅是顶级块。根据光标位置和配置的规则,基于规则的评分系统决定要定位哪个节点。

默认值: false

避免重新渲染

当向 nested 属性传递对象时,请始终在组件外定义它为常量。内联对象或计算属性中创建的对象会导致插件在每个渲染周期重新初始化,进而影响性能。

<template>
  <drag-handle :editor="editor" :nested="NESTED_CONFIG">
    <div>拖拽我!</div>
  </drag-handle>
</template>

<script>
import { DragHandle } from '@tiptap/extension-drag-handle-vue-3'

// 在组件外定义常量配置
const NESTED_CONFIG = { edgeDetection: { threshold: -16 } }

export default {
  components: { DragHandle },
  data() {
    return {
      // 将常量暴露给模板使用
      NESTED_CONFIG,
    }
  },
}
</script>

如果仅需简单启用,无需自定义配置:

<drag-handle :nested="true">
  <div>拖拽我!</div>
</drag-handle>

支持切换的完整示例

<template>
  <div v-if="editor">
    <button @click="nested = !nested">切换嵌套模式</button>
    <drag-handle :editor="editor" :nested="nestedOptions">
      <div class="drag-handle" />
    </drag-handle>
  </div>
  <editor-content :editor="editor" />
</template>

<script>
import { DragHandle } from '@tiptap/extension-drag-handle-vue-3'
import StarterKit from '@tiptap/starter-kit'
import { Editor, EditorContent } from '@tiptap/vue-3'

// 在组件外定义常量配置以防止重新渲染
const NESTED_CONFIG = { edgeDetection: { threshold: -16 } }

export default {
  components: {
    EditorContent,
    DragHandle,
  },
  data() {
    return {
      editor: null,
      nested: true,
    }
  },
  computed: {
    nestedOptions() {
      // 返回常量引用,而非新对象
      return this.nested ? NESTED_CONFIG : false
    },
  },
  mounted() {
    this.editor = new Editor({
      extensions: [StarterKit],
      content: '<ul><li>项目 1</li><li>项目 2</li></ul>',
    })
  },
  beforeUnmount() {
    this.editor?.destroy()
  },
}
</script>

有关详细的配置选项,包括边缘检测、自定义规则和允许的容器,请参阅 DragHandle 嵌套文档

命令

请参阅 DragHandle 扩展以获取可用的编辑器命令。