跳转到内容

拖拽插件

为树节点提供拖拽移动能力,支持插入到目标之前、之后或作为子节点。

安装

pnpm add @splicetree/plugin-dnd

使用

ts
import { createSpliceTree } from '@splicetree/core'
import dnd, { DropPosition } from '@splicetree/plugin-dnd'

const tree = createSpliceTree(data, {
  plugins: [dnd],
})
const { dragProps, ghostStyle } = tree
// 默认同时减去容器 padding 与 margin
// <div v-bind="ghostStyle()" />
// 关闭:不减任何边距
// <div v-bind="ghostStyle({ padding: false, margin: false })" />
// 仅减 padding(不减 margin)
// <div v-bind="ghostStyle({ padding: true, margin: false })" />

容器外部顶/底释放(设置顶级 0/最后索引)

将容器绑定 containerProps(),当在容器“外部顶部/底部”释放时:

  • 顶部:移动到顶级索引 0
  • 底部:移动到顶级末尾(索引为顶级最后一个)
vue
<template>
  <div class="relative flex flex-col items-stretch max-h-80 overflow-auto border w-full rounded p-1" v-bind="containerProps()">
    <div v-bind="ghostStyle()" class="z-50" />
    <div v-for="item in items" :key="item.id" v-bind="dragProps(item.id)">
      {{ item.original.title }}
    </div>
  </div>
</template>

示例

基本拖拽 + 统一占位(ghost)

loading

句柄拖拽(handle)

只在指定的句柄元素上允许拖拽,未设置时整行可拖拽。

ts
createSpliceTree(data, {
  plugins: [dnd],
  configuration: {
    dnd: {
      handle: '.handle', // 仅 .handle 元素上可触发拖拽
    },
  },
})
loading

禁止更新父字段

loading

禁止更新父字段需要您手动处理移动

当设置 configuration.dnd.autoUpdateParent: false 时,插件不会执行运行时移动与元数据写回。可以监听 move 事件按需处理:

ts
import { useSpliceTree } from '@splicetree/adapter-vue'
import dnd from '@splicetree/plugin-dnd'

const { events, moveNode } = useSpliceTree(data, {
  plugins: [dnd],
  configuration: { dnd: { autoUpdateParent: false } },
})

events.on('move', ({ node, parent, index }) => {
  const parentId = parent?.id
  const beforeId = parentId ? parent.getChildren()[index]?.id : undefined
  moveNode(node.id, parentId, beforeId)
})

禁止拖入后自动展开

loading

只读模式

loading

按节点行为控制

禁拖拽源

loading

拖这个节点:不能排到其它节点前后

loading

拖这个节点:文件/目录能进目录 不能进文件

loading

说明:这些设置说的是“被你拖的那个节点能不能做事”。比如 nestable: false 就是“拖这个节点,不能进其它节点里面”。不影响目标愿不愿意接收。可传函数/异步函数 (target) => boolean | Promise<boolean> 动态按目标判断;当返回 false 时占位(ghost)不会显示。

API

Configuration(简化)

选项类型默认值说明
configuration.dnd.autoUpdateParentbooleantrue是否在 onDrop 时执行实际移动与写回
configuration.dnd.autoExpandOnDropbooleantrue拖入后自动展开目标节点
configuration.dnd.readonlybooleanfalse全局只读,禁止所有拖拽与排序
configuration.dnd.colorstring#4224da统一占位(ghost)指示颜色
configuration.dnd.handlestring仅允许在句柄元素上拖拽(例如 .handle

Events

事件负载说明
move{ index: number, parent: Node|undefined, oldIndex: number, oldParent: Node|undefined, node: Node, event?: Event }节点移动事件

实例方法

名称参数说明
dropsrcId: string; targetId: string; position: DropPosition执行移动
onDragStartid: string标记拖拽源
onDragOverid: string; el: HTMLElement; e: DragEvent | MouseEvent更新目标悬停位置
onDragLeaveid: string清理悬停位置
onDroptargetId: string根据当前悬停位置执行移动
hoverPositions目标悬停位置缓存
draggingId当前正在拖拽的节点 id
dragPropsid: string; behavior?: { draggable?: boolean | (target: SpliceTreeNode) => boolean | Promise<boolean>; sortable?: boolean | (target: SpliceTreeNode) => boolean | Promise<boolean>; nestable?: boolean | (target: SpliceTreeNode) => boolean | Promise<boolean> }DOM 事件绑定集合(逐节点),可覆盖节点拖动/排序/拖入能力
ghostStyleopts?: { padding?: boolean, margin?: boolean }统一占位样式绑定对象;默认同时减去容器左右 padding 与 margin

节点方法

名称参数说明
getDropPosition()当前节点的悬停位置
isDragging()当前节点是否为拖拽源
isDisabled()当前节点是否被禁用