文档/API

useDnD 与监听器

拖拽状态及其事件,在 provider 之下的任何地方都可使用——还可以把 provider 本身交给另一个 Vue 应用。

编辑此页

本页由 AI 翻译,可能存在不准确之处。 阅读英文原文

Live

正在加载演示…

<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import TokenScene from './TokenScene.vue';
import StateInspector from './StateInspector.vue';
</script>

<template>
  <DnDProvider>
    <div class="demo">
      <TokenScene />
      <StateInspector />
    </div>
  </DnDProvider>
</template>

<style scoped>
.demo {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: 16px;
}
</style>

useDnD

function useDnD(): DnDState;

用于自定义 UI 的只读拖拽状态(高亮有效目标、加载指示、进度)。

const { status, active, over, selection, cancel } = useDnD();
const dragging = computed(() => status.value === 'dragging');

provider 拖拽的响应式状态。一旦放置结果确定,active 和 over 就会被清空,此时浮层仍在落位。

放置结果确定时,拖拽状态即告结束:active、over 和 pointer 变为 null(放置目标也不再接收),而浮层仍在以动画方式就位。派生的 UI 永远不会把旧的拖拽和新数据混在一起。在异步的 onBeforeDrop 做决定期间,状态保持松开时的样子,但页面已退出拖拽模式:它自己的光标和文本选择恢复正常(确认对话框可以照常工作),浮层停在被放下的位置等待。

拖拽进行时 status 为 'dragging';否则,在放置结果待定或仍有浮层在落位时为 'dropping';否则为 'idle'('activating' 和 'selecting' 除外)。新的拖拽不会等待落位:它立即开始,落位在它周围完成。

Readonly<Ref<DnDStatus>>

provider 当前在做什么(见 DnDStatus)。

Readonly<Ref<Active | null>>

进行中的拖拽;没有拖拽时为 null,放置一旦确定也变为 null。

Readonly<Ref<Over | null>>

拖拽下方的放置目标;不在任何目标上方时为 null。

Readonly<Ref<Coordinates | null>>

视口坐标中的指针位置,已应用修饰器;没有拖拽时为 null。

Readonly<Ref<Coordinates | null>>

被拖拽盒子的左上角在 over 中的实时位置:即每次移动时的 DnDEvent.position。下方没有目标时为 null。浮层组件可以读取它来显示将落到哪里(日历上的某个时间)。

{ progress: Readonly<Ref<number>> }

progress:在 status 为 'activating' 时,按下距离满足激活约束的进度,从 0 到 1:例如在长按期间逐渐填满的圆环。

Readonly<Ref<boolean>>

自动滚动正在移动某个容器。

DnDSelection

选中的可拖拽元素(见 DnDSelection)。

() => void

取消拖拽(它会飞回原处),或取消等待中的激活。

选中集合

选中的可拖拽元素,按 id 记录:拖拽其中一个会带上全部(多项拖拽)。由于按 id 保存,选中集合在元素卸载后依然保留(虚拟列表)。

ReadonlySet<Key>

选中的 id,响应式。

(id: Key) => boolean

id 是否被选中。

(...ids: Key[]) => void

选中这些 id。

(...ids: Key[]) => void

取消选中这些 id。

(id: Key, force?: boolean) => void

选中或取消选中 id;force: true 选中它,false 取消选中它。

(ids: Iterable<Key>) => void

只选中这些 id,其他都不选。

() => void

取消选中所有 id。

useDnDMonitor

function useDnDMonitor(monitor: DnDMonitor): void;

订阅 provider 下每次拖拽的事件,持续到调用它的组件(或 effect 作用域)销毁为止。

useDnDMonitor({
  onDragEnd: (e) => (e.dropped ? save(e) : undefined),
  onBeforeDrop: async (e) => ((await confirm()) ? 'accept' : 'reject'),
});

关于一次放置(onBeforeDrop),会先询问你的监听器,再询问目标。载荷见事件页面。

provider 下每次拖拽的钩子(useDnDMonitor)。

(event: DnDEvent) => void

拖拽在激活之后开始了。

(event: DnDEvent) => void

拖拽移动了(每帧最多一次)。

(event: DnDEvent) => void

拖拽下方的目标变了。

(event: DnDEvent) => MaybePromise<BeforeDropResult>

在放置提交之前运行(参见 BeforeDropResult):'reject' 拒绝它,返回 id 则只接受其中一部分。

(event: DnDEndEvent) => void

放置完成后的通知:可排序列表已经运行了它们的 onDrop 并完成了写入。

(event: DnDEvent) => void

拖拽被取消,或者它的放置被拒绝:项飞回原处。

(event: DnDEvent) => void

onBeforeDrop 返回了 'continue':没有发生放置,拖拽继续。

(event: DnDEvent | DnDEndEvent) => void

已结束的拖拽的浮层已经落位:在它的放置动画(或取消时的飞回)之后触发,参数是 onDragEnd(一个 DnDEndEvent)或 onDragCancel 收到的那个事件。下一次拖拽可能已在此期间开始:拖拽不会等待落位。

(event: KeyboardEvent, context: KeyboardMoveContext) => MaybePromise<Coordinates | undefined>

键盘拖拽:某个方向键对应的下一个指针位置(例如下一个可排序位置)。

按下方向键时,调用 getKeyboardCoordinates 所传入的参数。

Active

这次拖拽。

Coordinates

拖拽当前所在的位置,使用视口坐标。

Coordinates

所按方向键的单位向量。

useDnDContext 与 provideDnDContext

function useDnDContext(): DnDContext;

这个组件上方的 provider,作为供 provideDnDContext 使用的不透明句柄:它把 provider 桥接到 shadow root 和独立的 Vue 应用中。

function provideDnDContext(app: App, context: DnDContext): void;

把一个 provider(来自 useDnDContext())共享给另一个 Vue 应用,例如挂载在 shadow root 中的应用。

// In a component under the provider:
const context = useDnDContext();
// A second Vue app (a widget mounted in a shadow root) joins the same drag:
const widget = createApp(Widget);
provideDnDContext(widget, context);

useDnDContext() 返回的 provider,用来交给 provideDnDContext():之后另一个 Vue 应用(例如挂载在 shadow root 中的应用)就能与同一个 provider 协同工作。它是不透明的:没有公开成员,所以永远不会随库的内部实现而变化。