Библиотека Shopify Draggable предназначена для создания интерактивных, перетаскиваемых элементов на веб-странице. В основе лежит Drag and Drop API, реализованный через собственный абстрактный слой, который обеспечивает совместимость со всеми современными браузерами и позволяет гибко настраивать поведение элементов. Одним из ключевых применений является реализация сортируемых списков, где элементы можно менять местами без перезагрузки страницы.
Draggable оперирует контейнерами и
элементами, которые можно перетаскивать. Контейнер —
это DOM-элемент, содержащий один или несколько draggable-элементов.
Элементами могут быть <li>, <div>
или любой другой блочный или строчный элемент, у которого установлены
размеры и положение.
import { Sortable } from '@shopify/draggable';
const sortable = new Sortable(document.querySelectorAll('.list'), {
draggable: '.list-item',
});
В этом примере .list — контейнер, а
.list-item — элементы, которые можно сортировать.
Draggable предоставляет богатый набор событий для отслеживания процесса перетаскивания:
drag:start — начало перетаскивания.
Используется для изменения стилей, создания визуальных эффектов или
сохранения состояния.drag:move — перемещение элемента.
Позволяет реализовать динамические подсказки и ограничения.drag:stop — завершение перетаскивания.
Часто используется для обновления данных на сервере.sortable:sorted — элемент был успешно
перемещён внутри контейнера.sortable:stop — окончание сортировки
всех элементов.Пример добавления слушателя события:
sortable.on('sortable:sorted', (event) => {
console.log(`Элемент ${event.dragged.dataset.id} перемещён в позицию ${event.newIndex}`);
});
Для сортируемых списков ключевыми являются опции draggable, swapAnimation и mirror:
draggable — CSS-селектор элементов,
доступных для перетаскивания.swapAnimation — включает анимацию при
перестановке элементов, делая интерфейс более плавным.mirror — создаёт визуальную копию
перетаскиваемого элемента, позволяя оригиналу оставаться на месте до
завершения действия.const sortable = new Sortable(document.querySelectorAll('.list'), {
draggable: '.list-item',
mirror: {
constrainDimensions: true,
},
swapAnimation: {
duration: 300,
easingFunction: 'ease-in-out',
},
});
Использование mirror особенно важно для длинных списков, где пользователь должен видеть точное место, куда будет перемещён элемент.
Sortable позволяет работать с множественными контейнерами, что актуально для Kanban-досок или списков с несколькими категориями:
const sortable = new Sortable(document.querySelectorAll('.list-container'), {
draggable: '.list-item',
handle: '.handle',
});
Опция handle ограничивает область, с которой можно перетаскивать элемент, предотвращая случайное перемещение при клике по другим частям элемента.
Для синхронизации данных между контейнерами важно использовать
события sortable:sorted и sortable:stop и
обновлять массивы данных после каждого изменения.
Draggable предоставляет информацию о текущей позиции элемента через свойства:
oldIndex — исходная позиция в
контейнере.newIndex — новая позиция после
сортировки.dragged — сам DOM-элемент,
перемещённый пользователем.Эти данные можно использовать для обновления модели на стороне клиента или отправки на сервер:
sortable.on('sortable:stop', (event) => {
const movedItemId = event.dragged.dataset.id;
const oldIndex = event.oldIndex;
const newIndex = event.newIndex;
// Обновление данных
updateListOrder(movedItemId, oldIndex, newIndex);
});
При работе с большими списками важно учитывать производительность:
swapAnimation на тысячах
элементов может привести к снижению FPS.Draggable поддерживает nested lists, но при этом
необходимо внимательно отслеживать события и правильно конфигурировать
containers и draggable селекторы.
Для повышения UX можно использовать:
is-dragging,
is-mirror, is-swapping) для визуального
обозначения действий пользователя.Пример кастомного класса для перетаскиваемого элемента:
.list-item.is-dragging {
opacity: 0.6;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
transform: scale(1.05);
}
Draggable легко интегрируется с современными фронтенд-фреймворками, такими как React, Vue или Svelte. Важно синхронизировать состояние элементов в виртуальном DOM с событиями Draggable. Это позволяет:
Эффективная реализация сортируемых списков требует грамотного сочетания событий, кастомизации mirror, использования анимации и синхронизации данных. Это позволяет создавать интерактивные интерфейсы, которые сохраняют порядок элементов без потери производительности.