Сериализация порядка

Библиотека 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

Простейший способ инициализации 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 позволяет гибко управлять порядком элементов, легко сохранять и передавать их структуру для дальнейшей обработки, создавая динамичные и интерактивные интерфейсы.