Dragula — это легковесная библиотека для реализации перетаскивания элементов между контейнерами в веб-приложениях. Основная цель библиотеки — предоставление простого и интуитивно понятного API для работы с drag-and-drop, без необходимости глубокого погружения в низкоуровневые события мыши или touch-события.
В Dragula ключевыми элементами являются контейнеры, содержащие элементы для перетаскивания, и элементы, которые перемещаются между этими контейнерами. Контейнеры передаются в библиотеку через массив или DOM-элементы, а элементы внутри них идентифицируются автоматически.
Создание экземпляра Dragula производится с помощью функции
dragula(containers, options).
const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers, {
moves: (el, source, handle, sibling) => handle.classList.contains('handle'),
copy: false,
revertOnSpill: true
});
Ключевые параметры:
moves(el, source, handle, sibling) — функция,
определяющая, можно ли перетаскивать конкретный элемент. Возвращает
true или false.copy — при значении true перемещаемый
элемент копируется, при false — перемещается.revertOnSpill — при значении true элемент
возвращается на место, если был “выпущен” вне контейнеров.Dragula предоставляет ряд событий для управления поведением элементов:
drag — срабатывает при начале перетаскивания.drop — происходит после завершения перетаскивания в
новый контейнер.over и out — указывают на наведение
элемента на контейнер или выход из него.cancel — отменяет перетаскивание.Пример использования событий:
drake.on('drag', function(el) {
el.classList.add('is-dragging');
});
drake.on('drop', function(el, target, source, sibling) {
el.classList.remove('is-dragging');
console.log(`Элемент ${el.textContent} перемещен из ${source.id} в ${target.id}`);
});
Адаптер в контексте Dragula — это слой абстракции, который позволяет интегрировать библиотеку с различными фреймворками и архитектурами, сохраняя единый API для работы с элементами DOM.
Обертка — это вспомогательный компонент, инкапсулирующий Dragula в более удобный интерфейс для конкретного проекта. Она может добавлять кастомную логику, управление событиями или дополнительные проверки.
В React часто используют компонент-обертку для Dragula:
import React, { useEffect, useRef } from 'react';
import dragula from 'dragula';
import 'dragula/dist/dragula.css';
function DragulaContainer({ children }) {
const containerRef = useRef(null);
useEffect(() => {
const drake = dragula([containerRef.current]);
drake.on('drop', (el, target, source) => {
console.log('Элемент перемещен', el);
});
return () => drake.destroy();
}, []);
return <div ref={containerRef}>{children}</div>;
}
Такой подход позволяет интегрировать Dragula в реактивный рендеринг, сохраняя синхронизацию состояния с визуальным отображением.
В Vue создают директиву для управления контейнерами:
import dragula from 'dragula';
import 'dragula/dist/dragula.css';
export default {
mounted(el, binding) {
const drake = dragula([el], binding.value || {});
el.__drake__ = drake;
},
unmounted(el) {
if (el.__drake__) {
el.__drake__.destroy();
}
}
};
Директива позволяет подключать Dragula к любому элементу Vue-шаблона и автоматически очищать ресурсы при удалении компонента.
Адаптеры и обертки дают возможность:
moves, accepts).Простейший шаблон обертки:
class DragulaWrapper {
constructor(containers, options = {}) {
this.drake = dragula(containers, options);
this._initEvents();
}
_initEvents() {
this.drake.on('drag', this.onDrag.bind(this));
this.drake.on('drop', this.onDrop.bind(this));
}
onDrag(el) {
el.classList.add('dragging');
}
onDrop(el, target, source) {
el.classList.remove('dragging');
console.log(`Перемещен элемент ${el.id}`);
}
destroy() {
this.drake.destroy();
}
}
Такой подход позволяет централизованно управлять логикой перетаскивания и легко интегрировать Dragula в сложные приложения.
Адаптеры упрощают совместную работу Dragula с:
Использование оберток делает код чистым, повторно используемым и легко тестируемым, а также позволяет расширять функционал без изменения исходной библиотеки.