Что изменилось в новой версии
Vue DnD Kit v2 переосмысливает привычный механизм перетаскивания объектов в приложениях Vue 3. Вместо готовых UI‑компонентов библиотека предоставляет полностью «headless» ядро, которое управляет только логикой взаимодействия. Это освобождает разработчика от жёстких шаблонов и позволяет построить любую пользовательскую визуализацию: кастомные оверлеи, вложенные зоны, мульти‑перетаскивание и анимацию при отпускании. В основе новой версии лежит composable‑API, совместимый с реактивной системой Vue 3 и предоставляющий полностью типизированные хуки.
Архитектурные принципы
- Headless‑ядро – все расчёты координат, коллизий и состояния перетаскивания находятся в отдельном слое, не зависящем от DOM‑структуры. UI‑компоненты могут быть построены на любой библиотеке стилей или даже на чистом Canvas.
- Composable API – каждый аспект взаимодействия (инициализация, отслеживание, завершение) реализован отдельным хуком (
useDraggable,useDroppable,useDragOverlay). Хуки можно комбинировать в любой последовательности, что упрощает тестирование и переиспользование. - TypeScript‑first – типы экспортируются из пакета, позволяя IDE предлагать автодополнение и предотвращать типовые ошибки уже на этапе разработки.
- Модульность – библиотека разбита на небольшие пакеты (
@vue-dnd-kit/core,@vue-dnd-kit/sortable,@vue-dnd-kit/multi). Подключать можно только те части, которые действительно нужны в проекте.
Ключевые возможности
Кастомные оверлеи
Вместо стандартного «привязанного к элементу» визуального представления, v2 позволяет рендерить отдельный компонент‑оверлей, который следует за курсором независимо от исходного DOM‑узла. Хук useDragOverlay предоставляет координаты в реальном времени и событие завершения, а также возможность плавного перехода к целевой позиции.
Вложенные зоны
Благодаря системе приоритетов и механизму «bubbling» событий, можно создавать иерархию дроп‑зон. Внутри одной зоны может находиться другая, что особенно полезно в сложных UI‑редакторах (например, доски Kanban с вложенными карточками).
Мульти‑drag
Поддержка одновременного перетаскивания нескольких элементов реализована через массив идентификаторов в useDraggable. Библиотека автоматически рассчитывает границы, предотвращает наложения и синхронно обновляет позиции всех выбранных элементов.
Анимация при отпускании
После завершения операции onDrop передаёт финальные координаты и состояние (dropResult). На их основе можно задать CSS‑транзишн или использовать библиотеку анимаций (GSAP, Motion One) для плавного «притягивания» элемента к целевой зоне.
Перетаскивание между списками
@vue-dnd-kit/sortable предоставляет готовый набор хуков для сортировки элементов внутри списка и перемещения их между разными списками без потери порядка. Встроенная поддержка «placeholder» упрощает визуальное отображение места вставки.
Пример интеграции
<script setup lang="ts">
import { ref } from 'vue';
import { useDraggable, useDroppable, useDragOverlay } from '@vue-dnd-kit/core';
// Список перетаскиваемых элементов
const items = ref(['A', 'B', 'C', 'D']);
// Инициализация draggable для каждого элемента
function makeDraggable(id: string) {
return useDraggable({
id,
data: { label: id },
onDragStart: () => console.log('start', id),
onDragEnd: (e) => console.log('end', e),
});
}
// Зона, куда можно бросать элементы
const droppable = useDroppable({
id: 'target',
onDrop: (e) => alert(`Dropped ${e.draggableId}`),
});
// Оверлей, следящий за курсором
const overlay = useDragOverlay({
render: (draggable) => h('div', { class: 'my-overlay' }, draggable.data.label),
});
</script>
<template>
<div class="container">
<ul>
<li v-for="item in items" :key="item" v-bind="makeDraggable(item).attrs">
{{ item }}
</li>
</ul>
<div v-bind="droppable.attrs" class="drop-zone">
Drop here
</div>
<component :is="overlay.component" />
</div>
</template>
<style scoped>
.container { display: flex; gap: 2rem; }
.drop-zone { width: 200px; height: 200px; border: 2px dashed #aaa; }
.my-overlay { position: fixed; pointer-events: none; background: #fff; padding: .5rem; border: 1px solid #333; }
</style>
В примере демонстрируется базовый набор хуков: каждый элемент получает атрибуты draggable, зона принимает droppable, а оверлей рендерит кастомный элемент, следящий за курсором. Всё работает без каких‑либо предустановленных UI‑компонентов.
Производительность и масштабируемость
- Минимальный ре‑рендер: Хуки используют
refиcomputed, обновляя только те части состояния, которые действительно изменились. - Оптимизация коллизий: Расчёт столкновений происходит в
requestAnimationFrame, что гарантирует 60 fps даже при большом числе элементов. - Поддержка виртуального списка: При работе с тысячами элементов можно комбинировать
@vue-dnd-kit/coreсvue-virtual-scroller. Хуки работают с абстрактными идентификаторами, не требуя реального DOM‑узла до момента начала перетаскивания.
Миграция с версии 1
Перейти на v2 можно без полного переписывания кода, но рекомендуется:
- Заменить декларативные компоненты (
<Draggable>,<Droppable>) на соответствующие хуки. - Перенести стили в отдельные компоненты, используя
useDragOverlayдля визуального представления. - При необходимости подключить только нужные пакеты (
@vue-dnd-kit/sortableдля списков,@vue-dnd-kit/multiдля мульти‑drag).
Документация предоставляет миграционный гайд, где показаны типичные паттерны замены API.
Перспективы развития
Команда проекта планирует добавить поддержку pointer‑events для мобильных браузеров, а также встроенный accessibility layer, который будет генерировать ARIA‑атрибуты и поддерживать клавиатурные взаимодействия. В дальнейшем ожидается расширение набора хуков для работы с grid‑layout и canvas‑based визуализацией, что сделает Vue DnD Kit универсальным решением для сложных дизайнерских приложений.
Vue DnD Kit v2 задаёт новый уровень гибкости в реализации drag‑and‑drop для Vue 3, позволяя разработчикам сосредоточиться на пользовательском опыте, а не на ограничениях готовой библиотеки. Благодаря headless‑архитектуре, composable‑API и полной типизации, библиотека легко вписывается в любые архитектурные решения и открывает путь к созданию действительно кастомных интерактивных интерфейсов.