vue 自由拖拽vue3-dnd(四)

vue 自由拖拽vue3-dnd(四)-Composition API

提供了三个主要的钩子来将你的组件连接到 Vue3 DnD。并且提供了第四个钩子来让你在开发或测试中连接到 Vue3 DnD。

  • useDrag
  • useDrop
  • useDragLayer
  • useDragDropManager(开发/测试挂钩)

基本示例

使用 composition api 制作一个简单的可以拖放的盒子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script setup lang="ts">
import { useDrag } from 'vue3-dnd'
import { toRefs } from "@vueuse/core";

const [collect, drag, dragPreview] = useDrag(() => ({
// “type”是必需的。它由放置目标的“accept”使用。
type: 'BOX',
// collect 函数传入一个“监视器”实例,用于从 DnD 中获取需要的状态信息。
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
}))
// collect是一个Ref对象,默认取值需要从collect.value中获取,
// 可以使用toRefs将Ref对象转换为可解构的对象
const { isDragging } = toRefs(collect)
</script>

<template>
<!-- 这是可选的。默认情况下,dragPreview 将附加到 dragSource -->
<div :ref="dragPreview" :style="{ opacity: isDragging ? 0.5 : 1 }">
<div role="Handle" :ref="drag"/>
</div>
</template>

接下来,我们需要一个放置目标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script setup lang="ts">
import {useDrop} from 'vue3-dnd'
import {toRefs} from '@vueuse/core'

const [collect, drop] = useDrop(() => ({
// 允许放置的type(string|symbol),或者types
accept: 'BOX',
// 传递个collect的数据
collect: monitor => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
}))
const {canDrop, isOver} = toRefs(collect)
</script>

<template>
<div :ref="drop" :style="{ backgroundColor: isOver ? 'red' : 'white' }">
{{ canDrop ? 'Release to drop' : 'Drag a box here' }}
</div>
</template>

这样我们就实现了一个拖拽的盒子,你可以接着阅读单独的 API 文档,或者查看 示例

useDrag

useDrag 函数提供了一种将你的组件作为 拖拽源 连接到 DnD 的方法。它接收一个 Specification,你可以通过 type 指定拖拽的类型,通过 item 表示拖动源的数据,通过 collect 获取拖拽状态等等。

useDrag 返回了三个值:collect 函数的返回值,dragSourcedragPreview 的连接器函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
<script setup lang="ts">
import { useDrag } from 'vue3-dnd'

const [collectedProps, dragSource, dragPreview] = useDrag(() => ({
type: 'BOX',
item: { id: '1' },
}))
</script>

<template>
<div v-if="collectedProps.isDragging" :ref="dragPreview">dragPreview</div>
<div v-else :ref="dragSource">dragSource</div>
</template>

参数

useDrag 的参数可以是一个 Specification 对象,也可以是一个函数,返回一个 Specification 对象,有关 Specification 的详细信息,请参考 Specification

返回值

useDrag 返回一个数组,包含三个值:collect 函数的返回值,dragSourcedragPreview 的连接器函数

  • [0] - Collected Props
1
Ref<object>
  • 它是一个 Ref 对象,它的 value 指向 collect 函数的返回值,如果没有定义 collect 函数,它的 value 就是一个空对象

  • [1] - DragSource Connector

1
(el: Ref<HTMLElement> | HTMLElement, options?: DragSourceOptions) => HTMLElement
  • 拖拽源的连接器函数。它必须被调用,并且传入一个 Ref<HTMLElement> | HTMLElement 的可拖拽 DOM 元素;

  • 第二个参数是一个 options 对象,与 Specification 对象的 options 一致

  • [2] - DragPreview Connector

1
(el: Ref<HTMLElement> | HTMLElement, options?: DragPreviewOptions) => HTMLElement
  • 拖拽预览的连接器函数。它是可选的,默认使用 dragSource 作为预览元素,接收一个 Ref<HTMLElement> | HTMLElement 的可拖拽 DOM 元素;

  • 第二个参数是一个 options 对象,与 Specification 对象的 previewOptions 一致

Specification 对象

在了解 Specification 对象的基本用法之前,你可能需要先了解一下 DragSourceMonitor 对象。

Key 必填 类型 说明
type string | symbol 拖拽元素的类型
item object | () => object 对象时,它是一个描述被拖动数据的纯 JavaScript 对象。
这是拖放目标唯一可用的关于拖动源的信息,因此选择他们需要知道的最少数据很重要。
您可能很想在此处放置一个复杂的引用,但您应该尽量避免这样做,因为它会耦合拖动源和放置目标。使用类似的东西是个好主意 { id }
函数时,它在拖动操作开始时被触发并返回一个表示拖动操作的对象。如果返回 null,则取消拖动操作。
collect (monitor: DragSourceMonitor) => CollectedProps 一个收集器的函数。它应该返回一个普通对象并成为 useDrag 返回值中的第一个项。
previewOptions DragPreviewOptions 一个描述拖动预览选项的纯 JavaScript 对象。
options DragSourceOptions 一个普通对象,可选地包含以下任何属性:
dropEffect: 非必填,在此拖动中使用的拖放效果类型。可选值:`’move’
end (draggedItem: object, monitor: DragSourceMonitor) => void 当拖动停止时,end 函数会被调用。
你可以调用 monitor.didDrop() 以检查本次拖拽是否成功;
如果它成功,并且放置目标通过从其 drop() 方法返回一个普通对象来指定放置结果,那么它将作为 monitor.getDropResult() 的返回值。
这个方法是处理数据变化的好地方。
canDrag boolean | (monitor: DragSourceMonitor) => boolean 你可以使用它来指定当前是否允许拖动。默认为 true
如果您想禁用基于某些条件的拖动,则指定一个函数会很便捷。
注意:你不能在这个方法内部调用 monitor.canDrag()
isDragging boolean | (monitor: DragSourceMonitor) => boolean 默认情况下,只有发起拖动操作的拖动源才被认为是拖动的。
你可以通过定义自定义一个 isDragging 方法来覆盖此行为。
它可能会返回类似 props.id === monitor.getItem().id
注意:你不能在这个方法内部调用 monitor.isDragging()

useDrop

useDrop 函数提供了一种将你的组件作为 放置目标 连接到 DnD 的方法。它接收一个 Specification,你可以通过 accpet 指定允许放置的类型,通过 item 表示拖动源的数据,通过 collect 获取拖拽状态等等。

useDrop 返回了两个值:collect 函数的返回值,dropTarget 的连接器函数。

1
2
3
4
5
6
7
8
9
10
11
<script setup lang="ts">
import { useDrop } from 'vue3-dnd'

const [collectedProps, drop] = useDrop(() => ({
accept: ['BOX']
}))
</script>

<template>
<div :ref="drop">Drop Target</div>
</template>

参数

useDrop 的参数可以是一个 Specification 对象,也可以是一个函数,返回一个 Specification 对象,有关 Specification 的详细信息,请参考 Specification

返回值

useDrop 返回一个数组,包含两个值:collect 函数的返回值,dropTarget 的连接器函数

  • [0] - Collected Props

    1
    Ref<object>
    • 它是一个 Ref 对象,它的 value 指向 collect 函数的返回值,如果没有定义 collect 函数,它的 value 就是一个空对象
  • [1] - DragTarget Connector

    1
    Ref<(el: Ref<HTMLElement> | HTMLElement) => HTMLElement>
    • 放置目标的连接器函数。它必须被调用,并且传入一个 Ref<HTMLElement> | HTMLElement 的可被拖放 DOM 元素;

    • 第二个参数是一个 options 对象,与 Specification 对象的 options 一致

Specification 对象

在了解 Specification 对象的基本用法之前,你可能需要先了解一下 DropTargetMonitor 对象。

Key 必填 类型 说明
accept string | symbol | string[] | symbol[] 此放置目标只会对 指定类型的拖动源 做出反应。
collect (monitor: DropTargetMonitor) => CollectedProps 一个收集器的函数。
它应该返回一个普通对象并成为 useDrop 返回值中的第一个项。
options object 目前没什么用。
drop (item: object, monitor: DropTargetMonitor) => (void | Record<string, any>) 当拖拽元素放置在目标上时调用。你可以不返回任何东西,也可以返回一个普通对象。
如果你返回了一个对象,它将成为 dropResult, 并且在 dragend 方法中,可以通过 monitor.getDropResult() 获取到它。
如果你想根据不同的放置目标执行不同的操作,这将是一个不错的选择。
如果你的放置目标是嵌套的,那你可以通过 monitor.didDrop()monitor.getDropResult() 来检查嵌套目标是否已经处理。 这个方法和 dragend 方法,都是处理数据变化的好地方。
如果 canDrop() 方法返回 false,则不会调用此方法。
hover (item: object, monitor: DropTargetMonitor) => void 当拖拽组件经过组件上时调用该方法。 你可以通过检查 monitor.isOver({ shallow: true }) 来检查悬停是仅发生在当前目标上还是发生在内部的嵌套目标上。 和 drop() 方法不同的是:即使 canDrop() 返回了 false,该方法也会被调用。 你可以通过 monitor.canDrop() 来确认并避免这种情况。
canDrop (item: DragObject, monitor: DropTargetMonitor<DragObject, DropResult>) => boolean 用于指定放置目标是否能够接受此拖拽组件。
如果你希望总是允许,请忽略该方法。
如果你想基于 propsmonitor.getItem() 中的某些断言禁用放置,就可以使用它。
注意:你不能在这个方法中调用 monitor.canDrop()

useDragLayer

useDragLayer 函数提供了一种将你的组件作为 拖动层 连接到 DnD 的方法。

1
2
3
4
5
6
7
8
9
10
11
<script setup lang="ts">
import { useDragLayer } from 'vue3-dnd'

const collectedProps = useDragLayer(monitor => ({
item: monitor.getItem(),
}))
</script>

<template>
<div>...</div>
</template>

参数

useDragLayer 的参数是一个 collect 收集函数,它应该返回一个普通对象,并使你在组件中使用。

collect 收集函数的参数是一个 DragLayerMonitor 对象,它提供了一些监视器的方法,以便你可以获取监视器的状态。collect 函数的类型如下:

1
(monitor: DragLayerMonitor) => (void | object)

返回值

useDragLayer 返回一个 Ref 对象,它是 collect 函数的返回值。

1
Collected Props - Ref <object>
  • 它是一个Ref对象,它的value指向collect函数的返回值。

vue 自由拖拽vue3-dnd(四)
https://garlandqian.github.io/2024/02/02/vue3-dnd/vue自由拖拽vue3-dnd(四)/
作者
Garland Qian
发布于
2024年2月2日
许可协议