Для работы с Dragula в проектах на Vue.js требуется установка библиотеки через npm или yarn:
npm install dragula
или
yarn add dragula
В компоненте Vue.js Dragula импортируется следующим образом:
import dragula from 'dragula';
import 'dragula/dist/dragula.css';
Импорт CSS обязателен для корректного отображения эффектов перетаскивания и стилей элементов.
Dragula работает с DOM-элементами, поэтому в шаблоне Vue необходимо определить контейнеры:
<template>
<div class="container-wrapper">
<div class="container" ref="leftContainer">
<div class="item" v-for="item in leftItems" :key="item.id">{{ item.name }}</div>
</div>
<div class="container" ref="rightContainer">
<div class="item" v-for="item in rightItems" :key="item.id">{{ item.name }}</div>
</div>
</div>
</template>
Использование ref позволяет получить доступ к
DOM-элементам для передачи их в Dragula.
Инициализация происходит в хуке жизненного цикла
mounted, чтобы контейнеры уже существовали в DOM:
export default {
data() {
return {
leftItems: [
{ id: 1, name: 'Элемент A' },
{ id: 2, name: 'Элемент B' }
],
rightItems: [
{ id: 3, name: 'Элемент C' }
]
};
},
mounted() {
const left = this.$refs.leftContainer;
const right = this.$refs.rightContainer;
this.drake = dragula([left, right]);
this.drake.on('drop', (el, target, source, sibling) => {
this.updateItems(el, source, target, sibling);
});
},
methods: {
updateItems(el, source, target, sibling) {
const itemId = Number(el.dataset.id);
const sourceArray = source === this.$refs.leftContainer ? this.leftItems : this.rightItems;
const targetArray = target === this.$refs.leftContainer ? this.leftItems : this.rightItems;
const index = sourceArray.findIndex(item => item.id === itemId);
if (index === -1) return;
const [movedItem] = sourceArray.splice(index, 1);
let siblingIndex = targetArray.length;
if (sibling) {
const siblingId = Number(sibling.dataset.id);
siblingIndex = targetArray.findIndex(item => item.id === siblingId);
}
targetArray.splice(siblingIndex, 0, movedItem);
}
}
};
Каждый элемент в шаблоне должен иметь data-id для
корректного отслеживания перемещений:
<div class="item"
v-for="item in leftItems"
:key="item.id"
:data-id="item.id">
{{ item.name }}
</div>
Dragula поддерживает ряд опций:
true для
разрешения перетаскивания конкретного элемента.Пример использования опций:
this.drake = dragula([left, right], {
copy: false,
revertOnSpill: true,
moves: (el, source, handle, sibling) => {
return !el.classList.contains('locked');
},
accepts: (el, target, source, sibling) => {
return target !== source;
}
});
Dragula напрямую изменяет DOM, но Vue.js работает с реактивными
массивами. Чтобы синхронизировать состояние, необходимо обновлять
массивы через методы Vue, как показано в updateItems. Это
обеспечивает правильное отображение элементов при повторных рендерах и
при изменении данных.
Dragula предоставляет набор событий для работы с перетаскиванием:
drag — когда элемент начинает перетаскиваться.drop — при сбросе элемента.over / out — при наведении на
контейнер.cancel — при отмене перетаскивания.Пример подписки:
this.drake.on('drag', el => {
el.classList.add('is-dragging');
});
this.drake.on('drop', el => {
el.classList.remove('is-dragging');
});
При уничтожении компонента важно отключить Dragula, чтобы избежать утечек памяти:
beforeUnmount() {
this.drake.destroy();
}
Dragula поддерживает работу с динамическими компонентами, но нужно
обновлять контейнеры при изменении DOM. Для этого можно использовать
nextTick:
this.$nextTick(() => {
this.drake.containers = [this.$refs.leftContainer, this.$refs.rightContainer];
});
Это гарантирует, что новые элементы будут участвовать в перетаскивании без нарушения реактивности Vue.