为自研Tree组件实现节点拖拽功能,实现节点拖拽后的可插入位置识别,下一小节实现节点插入和更新。
目录

用法示例
操作演示:
自研Tree组件功能演示:节点拖拽(上)
ts类型和属性定义
src/components/tree/types.ts
启用拖拽属性定义
export interface OptionProps {
...
draggable?: boolean // 启用拖拽
}
用户可以实现一个Function
的组件属性来自定义哪些节点允许drop
:
// 导出tree组件的属性定义
export const props = {
...
// 允许drop的逻辑判断方法
allowDrop: Function as PropType<AllowDropFunction>,
...
} as const // 注意属性设置为只读的,外面不能修改,同时也避免传空的情况
// 允许drop的函数定义
export declare type AllowDropFunction = (draggingNode: IFlatTreeNode, dropNode: IFlatTreeNode, type: DropType) => boolean
定义drop的操作类型,有效释放是,在一个节点前、后或者位于一个节点内:
// 拖拽释放的操作类型
export declare type DropType = 'before' | 'after' | 'inner'
拖拽事件处理函数定义
// 拖拽事件处理函数定义
export interface DragEvents {
dragStart: (event: DragEvent, node: IFlatTreeNode) => void
dragOver: (event: DragEvent, node: IFlatTreeNode) => void
dragEnd: (event: DragEvent) => void
}
记录拖拽的状态信息
// 记录拖拽过程中的状态信息
export interface DragState {
draggingNode?: IFlatTreeNode // 被拖拽的节点
dropNode?: IFlatTreeNode // 释放到目标节点
allowDrop?: boolean // 是否允许拖动
dropType?: DropType // 释放的类型枚举
}
拖拽模块的核心实现
src/components/tree/use-drag.ts
import {
DragEvents, DragState, IdType, IFlatTreeNode, Props } from './types'
import {
computed, ComputedRef, Ref, ref } from 'vue'
// 拖拽上下文
export interface UseDragContext {
dragEvents: DragEvents // 封装的拖拽事件处理逻辑
dragState: DragState // 当前拖拽状态信息
dragging: ComputedRef<boolean> // 是否正在拖拽中的布尔计算属性
dragNodeIds: Ref<Array<IdType>> // 拖拽的扁平化节点id列表
}
const calcDragNodeIds = (node: IFlatTreeNode, data: IFlatTreeNode