Библиотека Shopify Draggable предоставляет мощный инструмент для создания перетаскиваемых списков, сеток и элементов интерфейса. Одним из ключевых аспектов работы с интерактивными списками является сериализация порядка элементов, позволяющая сохранить текущую последовательность элементов для дальнейшей обработки, например, отправки на сервер или локального хранения.
Сериализация в контексте Draggable означает преобразование текущего DOM-порядка элементов в структурированный объект или массив, который отражает их последовательность. Обычно это массив идентификаторов элементов, атрибутов или объектов с дополнительными данными.
Ключевые моменты:
data-id).data-id и структура элементовДля корректной сериализации рекомендуется добавлять каждому элементу список уникальный идентификатор:
<ul id="sortable-list">
<li data-id="1">Элемент 1</li>
<li data-id="2">Элемент 2</li>
<li data-id="3">Элемент 3</li>
</ul>
Draggable будет использовать эти атрибуты для формирования последовательности при вызове методов сериализации.
Простейший способ инициализации Draggable для списка:
import { Sortable } from '@shopify/draggable';
const container = document.querySelector('#sortable-list');
const sortable = new Sortable(container, {
draggable: 'li',
});
Здесь ключевой параметр — draggable, определяющий
элементы, которые можно перетаскивать.
После завершения операции перетаскивания можно использовать событие
sortable:stop для сериализации:
sortable.on('sortable:stop', (event) => {
const items = Array.from(container.children);
const order = items.map(item => item.dataset.id);
console.log(order); // ["1", "3", "2"] при изменении порядка
});
Особенности:
Array.from(container.children) создает массив
DOM-элементов в текущем порядке.item.dataset.id возвращает значение атрибута
data-id для каждого элемента.Для более сложных структур часто необходимо сериализовать элементы в объекты с дополнительными свойствами:
const serialized = items.map(item => ({
id: item.dataset.id,
content: item.textContent.trim(),
position: Array.from(container.children).indexOf(item) + 1
}));
console.log(serialized);
/*
[
{ id: "1", content: "Элемент 1", position: 1 },
{ id: "3", content: "Элемент 3", position: 2 },
{ id: "2", content: "Элемент 2", position: 3 }
]
*/
Такой подход позволяет хранить полноценные объекты с идентификатором, содержимым и порядковым номером, что облегчает дальнейшую интеграцию с базой данных или API.
Сериализованные данные обычно отправляются на сервер методом
fetch или axios:
fetch('/update-order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ order: serialized })
})
.then(response => response.json())
.then(data => console.log('Сервер принял новый порядок', data))
.catch(error => console.error('Ошибка при сохранении порядка', error));
Рекомендуется использовать объект с ключом
order, чтобы сервер мог легко обработать
данные.
Draggable поддерживает nested lists, где элементы могут содержать дочерние списки. Сериализация требует рекурсивного обхода:
function serializeList(list) {
return Array.from(list.children).map(item => {
const nested = item.querySelector('ul');
return {
id: item.dataset.id,
children: nested ? serializeList(nested) : []
};
});
}
const nestedOrder = serializeList(document.querySelector('#nested-list'));
console.log(nestedOrder);
Результат — объект, отражающий структуру дерева элементов, что особенно полезно для меню и категорий с иерархией.
Draggable предоставляет следующие события для работы с сериализацией:
sortable:start — начало перетаскивания элемента.sortable:sort — во время изменения позиции.sortable:stop — окончание операции перетаскивания,
наиболее подходящее место для сериализации.Использование sortable:stop гарантирует, что массив
будет актуален и соответствует последнему состоянию
DOM.
data-id, особенно при
динамическом создании элементов.stop, а не при каждом движении, чтобы
избежать лишних вычислений.С помощью этих методов библиотека Shopify Draggable позволяет гибко управлять порядком элементов, легко сохранять и передавать их структуру для дальнейшей обработки, создавая динамичные и интерактивные интерфейсы.