Типы данных и интерфейсы

Dragula — это легковесная библиотека для организации drag-and-drop интерфейсов в веб-приложениях на JavaScript. Она обеспечивает перенос элементов между контейнерами и внутри одного контейнера с минимальной настройкой. Ключевым преимуществом является простота использования при высокой гибкости: события drag-and-drop обрабатываются автоматически, но при этом доступны расширенные настройки.

Основная идея Dragula заключается в отслеживании элементов DOM и их перемещении между контейнерами, заданными в настройках. Библиотека не накладывает строгих ограничений на структуру данных и позволяет работать с любыми HTML-элементами.


Инициализация и базовые методы

Создание Dragula начинается с вызова функции dragula, которой передается массив контейнеров:

const containers = [document.querySelector('#container1'), document.querySelector('#container2')];
const drake = dragula(containers);
  • drake — объект, через который управляется поведение drag-and-drop.
  • Контейнеры могут быть как один, так и несколько; можно динамически добавлять новые.

Методы объекта drake:

  • drake.containers — массив текущих контейнеров.
  • drake.start(item) — принудительно начинает перенос указанного элемента.
  • drake.cancel(revert = true) — отменяет текущее перемещение.
  • drake.remove() — удаляет элемент из DOM после переноса, если это необходимо.
  • drake.destroy() — полностью отключает Dragula для всех контейнеров.

События

Dragula предоставляет набор событий, позволяющих гибко контролировать процесс перетаскивания:

  • drag — начинается перетаскивание элемента.
  • drop — элемент был отпущен в контейнере.
  • over — элемент находится над контейнером.
  • out — элемент покинул контейнер.
  • cancel — операция переноса была отменена.
  • cloned — элемент был склонирован (используется при настройках копирования).

Пример подписки на событие:

drake.on('drop', function(el, target, source, sibling) {
    console.log('Элемент перемещен:', el);
    console.log('Новый контейнер:', target);
});
  • el — перемещаемый элемент.
  • target — контейнер, в который элемент помещен.
  • source — исходный контейнер.
  • sibling — элемент, перед которым вставляется переносимый элемент, либо null.

Настройки и опции

Dragula позволяет тонко настраивать поведение через объект опций при инициализации:

const drake = dragula(containers, {
    moves: function(el, source, handle, sibling) {
        return handle.classList.contains('handle');
    },
    accepts: function(el, target, source, sibling) {
        return !target.classList.contains('forbidden');
    },
    copy: false,
    revertOnSpill: true
});

Ключевые параметры:

  • moves(el, source, handle, sibling) — функция, определяющая, можно ли начать перенос с данного элемента. Обычно используется для ограничения перетаскивания только по определенной области (например, по «ручке»).
  • accepts(el, target, source, sibling) — определяет, можно ли поместить элемент в конкретный контейнер.
  • copy — если true, элементы копируются вместо перемещения.
  • revertOnSpill — возвращает элемент в исходное положение при броске вне контейнеров.
  • direction — ограничивает направление перемещения ('vertical' или 'horizontal').
  • invalid — функция, которая запрещает перетаскивание определенных элементов (например, кнопок или заголовков).

Работа с данными

Хотя Dragula напрямую работает с DOM, управление данными часто необходимо для синхронизации с состоянием приложения. Обычно используется два подхода:

  1. Синхронизация с массивами объектов:
let items = ['А', 'Б', 'В'];

drake.on('drop', function(el, target, source, sibling) {
    const movedItem = el.dataset.item;
    items = items.filter(i => i !== movedItem);
    // Вставка в новое место
    items.splice(Array.from(target.children).indexOf(el), 0, movedItem);
});
  1. Использование идентификаторов элементов:
  • Каждый элемент получает уникальный data-id.
  • При событии drop обновляется соответствующий объект в массиве данных.
  • Это позволяет поддерживать модель данных в синхронизации с DOM без полного пересоздания списка.

Продвинутые техники

  • Динамические контейнеры: контейнеры можно добавлять и удалять после инициализации через drake.containers.push(newContainer).
  • Клонирование элементов: использование параметра copy позволяет создавать копии элементов при перетаскивании, полезно для списков шаблонов.
  • Drag handles: ограничение начала перемещения определенной областью элемента повышает удобство UX.
  • Валидация вставки: функция accepts позволяет создавать сложные правила, например, запрет перемещения одного типа элементов в контейнер другого типа.

Взаимодействие с другими библиотеками

Dragula хорошо интегрируется с фреймворками типа React или Vue через управление жизненным циклом контейнеров и элементов. Важно использовать destroy() при удалении контейнеров, чтобы избежать утечек памяти. Также можно комбинировать Dragula с библиотеками для анимации, например, с GSAP, для плавного перемещения элементов.


Практические советы

  • Использовать revertOnSpill для предотвращения случайных потерь элементов.
  • Добавлять CSS-классы для визуальной индикации активного перемещения.
  • Использовать события out и over для динамического изменения состояния контейнеров.
  • При работе с большим количеством элементов оптимизировать DOM-операции, избегая частых перерисовок.

Dragula сочетает простоту и гибкость, позволяя создавать как базовые списки с drag-and-drop, так и сложные интерфейсы с множественными контейнерами, копированием элементов и строгой валидацией.