Документация/API
useDnD и мониторы
Состояние драга и его события в любом месте под провайдером — и сам провайдер, переданный другому Vue-приложению.
Страница переведена ИИ и может содержать неточности. Читать английский оригинал
Загружаем демо…
<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');
Состояние драга провайдера, реактивное. active и over очищаются, как только бросок решён,
пока оверлей ещё приземляется.
Состояние драга заканчивается, как только бросок решён: active, over и pointer равны null (и зоны сброса перестают принимать), пока оверлей ещё анимируется к своему месту. Производный UI никогда не смешивает старый драг с новыми данными. Пока асинхронный onBeforeDrop принимает решение, состояние остаётся таким, каким было в момент отпускания, но страница выходит из режима драга: возвращаются её собственный курсор и выделение текста (диалог подтверждения работает как обычно), а оверлей ждёт там, где его отпустили.
status равен 'dragging', пока идёт драг, иначе 'dropping', пока решается бросок или ещё приземляется оверлей, иначе 'idle' (не считая 'activating' и 'selecting'). Новый драг не ждёт приземлений: он начинается сразу, а они завершаются вокруг него.
Readonly<Ref<DnDStatus>>Что делает провайдер (см. DnDStatus).
Readonly<Ref<Active | 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: насколько нажатие продвинулось к своему условию активации, от 0 до 1, пока status равен 'activating': например, кольцо, которое заполняется во время долгого нажатия.
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;Подписывается на события каждого драга под провайдером, пока живёт вызвавший компонент (или effect scope).
useDnDMonitor({
onDragEnd: (e) => (e.dropped ? save(e) : undefined),
onBeforeDrop: async (e) => ((await confirm()) ? 'accept' : 'reject'),
});
Ваши мониторы спрашиваются о броске (onBeforeDrop) раньше цели. Данные событий — на
странице событий.
Хуки для каждого драга под провайдером (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) => voidonBeforeDrop ответил 'continue': броска не было, и драг продолжается.
(event: DnDEvent | DnDEndEvent) => voidОверлей завершённого драга приземлился: после анимации броска (или полёта обратно при отмене), с событием, которое получил onDragEnd (DnDEndEvent) или onDragCancel. Следующий драг к этому времени мог уже начаться: драги не ждут приземлений.
(event: KeyboardEvent, context: KeyboardMoveContext) => MaybePromise<Coordinates | undefined>Перетаскивание с клавиатуры: следующая позиция указателя для клавиши-стрелки (например, следующий слот сортировки).
С чем вызывается getKeyboardCoordinates для клавиши-стрелки.
useDnDContext и provideDnDContext
function useDnDContext(): DnDContext;Провайдер над этим компонентом — как непрозрачный дескриптор для provideDnDContext: он пробрасывает провайдер в shadow root и отдельные Vue-приложения.
function provideDnDContext(app: App, context: DnDContext): void;Делится провайдером (из 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(), — чтобы передать его в provideDnDContext(): тогда другое Vue-приложение (например, смонтированное в shadow root) работает с тем же провайдером. Непрозрачный: у него нет публичных членов, поэтому он не меняется вместе с внутренностями библиотеки.