Структура DOM для draggable элементов

Библиотека Shopify Draggable построена на принципах модульного взаимодействия с элементами DOM и требует правильной организации структуры для корректной работы перетаскивания. Основная идея заключается в разделении интерфейса на контейнеры и элементы, которые можно перемещать, а также в четкой иерархии, обеспечивающей совместимость с событиями библиотеки.


Контейнеры и элементы

Контейнер — это элемент, внутри которого происходят перетаскивания. Он служит родителем для всех draggable элементов и обеспечивает контроль над границами перемещения. Обычно контейнер обозначается через класс или атрибут, например:

<div class="draggable-container">
  <div class="draggable-item">Элемент 1</div>
  <div class="draggable-item">Элемент 2</div>
  <div class="draggable-item">Элемент 3</div>
</div>

Ключевые моменты:

  • Контейнер должен быть одним родительским элементом для всех draggable элементов, чтобы библиотека могла корректно отслеживать позиции.
  • Атрибуты position для контейнера не обязательны, но рекомендуется использовать relative для удобства позиционирования перемещаемых элементов.
  • Контейнер может содержать вложенные структуры, но для простого drag-and-drop лучше избегать глубокой вложенности, чтобы события не перехватывались дочерними элементами.

Draggable элемент — это элемент, который можно перетаскивать внутри контейнера. Он должен быть отдельным DOM-узлом и иметь уникальный класс или идентификатор для правильной инициализации:

const container = document.querySelector('.draggable-container');

const draggable = new Draggable(container, {
  draggable: '.draggable-item'
});
  • Класс draggable-item используется для выбора всех элементов, которые будут перемещаться.
  • Каждый элемент должен иметь фиксированную высоту и ширину, особенно если включен режим сортировки, чтобы библиотека могла точно вычислять позицию.

Вложенные структуры и списки

Для сортируемых списков рекомендуется использовать следующий DOM:

<ul class="draggable-list">
  <li class="draggable-item">Элемент A</li>
  <li class="draggable-item">Элемент B</li>
  <li class="draggable-item">Элемент C</li>
</ul>

Особенности:

  • Список (ul или ol) выступает контейнером, а li — draggable элементами.
  • Вложенные списки разрешены, но каждый вложенный контейнер требует отдельной инициализации Draggable для корректного взаимодействия.
  • Для упрощения вычислений лучше избегать смешивания разных уровней элементов в одном контейнере.

Placeholder и Mirror элементы

Mirror элемент — это визуальное отображение перетаскиваемого элемента, создаваемое библиотекой автоматически. DOM должен предусматривать возможность свободного позиционирования:

  • Mirror элемент создается поверх других элементов и не должен находиться внутри контейнера в оригинальном DOM.
  • Его стили можно настраивать через CSS: position: fixed, pointer-events: none, z-index выше, чем у других элементов.

Placeholder используется для обозначения места, где элемент будет после отпускания:

.draggable-item--placeholder {
  border: 2px dashed #ccc;
  height: 50px;
}
  • Placeholder вставляется динамически в DOM во время drag-события.
  • Необходимо предусмотреть CSS для высоты и ширины, чтобы контейнер не “скакал” при перемещении.

Иерархия и атрибуты

Правильная иерархия элементов обеспечивает предсказуемое поведение drag-and-drop:

  1. Контейнер — родительский элемент с классом или идентификатором.
  2. Draggable элементы — непосредственные дети контейнера.
  3. Вложенные контейнеры — могут существовать, но требуют отдельной инициализации.
  4. Mirror и placeholder — создаются библиотекой, не должны ломать основную структуру.

Дополнительно можно использовать атрибуты:

  • data-id для уникальной идентификации элементов.
  • data-draggable для явного указания, какие элементы перетаскиваемые.
  • aria-grabbed и другие ARIA атрибуты для доступности.

Советы по оптимизации DOM

  • Минимизировать количество уровней вложенности для повышения производительности.
  • Стараться использовать блоки с одинаковыми размерами, чтобы библиотека могла быстро вычислять позиции.
  • Избегать абсолютного позиционирования дочерних элементов внутри контейнера, если используется сортировка.
  • Обеспечить уникальные идентификаторы или классы для каждого draggable элемента для точного отслеживания событий.

Эта структура DOM является фундаментальной для использования всех возможностей Shopify Draggable, включая сортировку, совместную работу нескольких контейнеров и динамическое создание элементов. Правильная организация контейнеров, draggable элементов и их визуальных отображений (mirror/placeholder) напрямую влияет на стабильность и плавность drag-and-drop.