Dragula — это лёгкая библиотека JavaScript для перетаскивания элементов между контейнерами. Она обеспечивает удобный интерфейс для drag-and-drop, минимизируя необходимость ручного управления событиями мыши и состояниями элементов. Основная концепция Dragula заключается в автоматическом отслеживании источников перетаскивания и целевых контейнеров, а также в обработке визуальной обратной связи при перемещении.
Инициализация выполняется с помощью вызова функции
dragula с массивом контейнеров:
const containers = [document.getElementById('left'), document.getElementById('right')];
const drake = dragula(containers);
После этого все дочерние элементы указанных контейнеров становятся перетаскиваемыми.
Dragula предоставляет ряд опций для тонкой настройки поведения:
moves: function (el, source, handle, sibling) {
return handle.classList.contains('handle');
}
Только элементы с указанным классом handle становятся
доступными для перемещения.
accepts: function (el, target, source, sibling) {
return target.id !== 'forbidden';
}
Элемент не может быть перемещён в контейнер с id
forbidden.
copy: true
revertOnSpill: true
Эти параметры дают полный контроль над правилами перетаскивания и перемещения элементов.
Dragula генерирует ряд событий, которые позволяют реагировать на действия пользователя:
Пример использования событий:
drake.on('drag', function(el) {
el.style.opacity = '0.5';
});
drake.on('drop', function(el, target) {
el.style.opacity = '1';
console.log('Элемент перемещён в контейнер:', target.id);
});
drake.on('out', function(el, container) {
container.style.background = '';
});
Эти события позволяют реализовать визуальные эффекты, хранение состояния в базе данных и другие интерактивные функции.
Можно задать ограничения на перемещение элементов:
.horizontal-container { display: flex; flex-direction: row; }
.vertical-container { display: flex; flex-direction: column; }
moves
предотвращает перемещение определённых элементов.accepts:accepts: function (el, target) {
return target.children.length < 5;
}
Dragula поддерживает копирование элементов и удаление при сбросе вне контейнера:
const drake = dragula(containers, {
copy: function (el, source) {
return source.id === 'source-list';
},
removeOnSpill: true
});
При этом элементы из source-list будут копироваться, а
если элемент сброшен вне контейнеров, он будет удалён.
Контейнеры можно добавлять и удалять во время работы приложения:
drake.containers.push(document.getElementById('new-container'));
drake.containers.splice(drake.containers.indexOf(oldContainer), 1);
Это позволяет создавать интерфейсы с динамически изменяемыми зонами перетаскивания.
Dragula интегрируется с любыми структурами данных. Для синхронизации
состояния можно использовать событие drop:
drake.on('drop', function(el, target, source, sibling) {
const itemId = el.dataset.id;
updateDataModel(itemId, source.id, target.id);
});
Функция updateDataModel может изменять массив или
объект, отражающий текущее состояние интерфейса, обеспечивая
сохранение порядка элементов.
Dragula добавляет классы к элементам и контейнерам для управления стилями:
gu-mirror — копия элемента, перемещаемая мышью.gu-transit — элемент в процессе перемещения.gu-hide — скрывает оригинал при копировании.gu-unselectable — предотвращает выделение текста при
перетаскивании.Пример CSS для визуальной обратной связи:
.gu-mirror {
opacity: 0.7;
border: 2px dashed #333;
background: #f0f0f0;
}
.gu-transit {
opacity: 0.5;
}
Dragula оптимизирован для работы с большим количеством элементов:
moves для фильтрации перетаскиваемых
элементов, чтобы сократить обработку событий.Эти методы позволяют реализовать интерактивные интерфейсы с сотнями элементов без снижения производительности.
Dragula можно использовать совместно с React, Vue или Angular.
Основной принцип — инициализация после рендера DOM и
управление состоянием через события drop или
remove.
Пример для React:
useEffect(() => {
const drake = dragula([leftRef.current, rightRef.current]);
drake.on('drop', (el, target) => {
handleDrop(el, target);
});
return () => drake.destroy();
}, []);
Это позволяет сохранять реактивность компонентов и управлять состоянием приложения через стандартные методы фреймворка.