Управление состоянием

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


События и жизненный цикл элементов

Draggable использует подписку на события для управления состоянием. Основные события включают:

  • drag:start — инициируется при начале перетаскивания. В момент этого события элемент получает состояние активного перетаскивания.
  • drag:move — происходит на каждом кадре движения элемента. Используется для обновления позиции и взаимодействия с другими объектами.
  • drag:stop — завершается процесс перетаскивания. Элемент возвращается в исходное состояние или принимает новое в зависимости от логики сортировки.
  • sortable:swap — вызывается при смене позиции элементов в sortable контейнере, что позволяет синхронизировать визуальное состояние с внутренним порядком.
  • sortable:sorted — фиксирует итоговое состояние после завершения сортировки, позволяя обновлять данные в модели.

Каждое событие передаёт объект Event, содержащий информацию о состоянии перетаскиваемого элемента, его родителя, позиции и индексах. Использование этих данных позволяет реализовать детальное управление состоянием без прямой модификации DOM.


Управление классами состояния

Draggable автоматически добавляет CSS-классы для отражения текущего состояния:

  • draggable--is-dragging — элемент находится в процессе перетаскивания.
  • draggable--is-moving — элемент перемещается внутри контейнера.
  • draggable--is-swapping — временное состояние при перестановке с другим элементом.
  • draggable--over — указывает на пересечение с потенциальным целевым контейнером.

Эти классы можно использовать для динамического изменения стиля элементов, отображения подсказок, анимаций и визуальной обратной связи. Для полного контроля рекомендуется комбинировать CSS-классы с событиями Draggable, чтобы состояние всегда соответствовало логике приложения.


Управление внутренним состоянием элементов

В сложных интерфейсах требуется синхронизация состояния Draggable с внутренней моделью данных. Для этого используют:

  1. Идентификаторы элементов — каждому draggable элементу присваивается уникальный id или data-* атрибут. Это позволяет точно сопоставлять визуальное состояние с данными.
  2. Обновление массивов и моделей — при событиях sortable:swap и sortable:sorted изменяется порядок элементов в массиве. Это обеспечивает актуальность состояния модели относительно DOM.
  3. Свойства пользовательского состояния — можно хранить дополнительную информацию, например, флаги активности, временные состояния перетаскивания или приоритеты сортировки.

Пример синхронизации с моделью данных:

const draggable = new Draggable.Sortable(container, {
  draggable: '.item'
});

draggable.on('sortable:sorted', (event) => {
  const { oldIndex, newIndex } = event;
  myDataArray.splice(newIndex, 0, myDataArray.splice(oldIndex, 1)[0]);
});

Динамическое включение и отключение перетаскивания

Draggable позволяет изменять состояние возможности перетаскивания элементов без пересоздания экземпляра. Методы:

  • draggable.disable() — полностью блокирует перетаскивание всех элементов.
  • draggable.enable() — возвращает возможность перемещения.
  • draggable.destroy() — полностью удаляет управление состоянием и очищает слушатели событий.

Для отдельных элементов можно управлять состоянием через атрибуты или проверку внутри события drag:start:

draggable.on('drag:start', (event) => {
  if (event.source.classList.contains('locked')) {
    event.cancel();
  }
});

Интеграция с анимациями состояния

Shopify Draggable тесно интегрируется с анимациями состояния элементов через CSS transitions и requestAnimationFrame. Использование событий drag:move и sortable:swap позволяет плавно обновлять позиции элементов, изменять прозрачность, масштаб и цвет для визуального отображения состояния:

.item {
  transition: transform 0.2s ease, opacity 0.2s ease;
}

.item.draggable--is-dragging {
  opacity: 0.8;
  transform: scale(1.05);
}

Такой подход поддерживает консистентность состояния и улучшает UX без необходимости сложного управления DOM вручную.


Практические паттерны управления состоянием

  1. Отложенные действия — выполнение операций после завершения сортировки (sortable:sorted), чтобы состояние модели оставалось точным.
  2. Кастомные флаги состояния — хранение состояния элементов в объекте или Map для быстрого доступа и предотвращения конфликтов.
  3. События для внешних компонентов — при изменении состояния можно триггерить собственные события, синхронизируя Draggable с другими UI-компонентами.

Эффективное управление состоянием позволяет реализовать:

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

Рекомендации по устойчивому управлению состоянием

  • Всегда использовать события Draggable для обновления модели данных, а не полагаться на прямые манипуляции DOM.
  • Хранить уникальные идентификаторы элементов для точного отслеживания их состояния.
  • Разделять визуальное состояние (CSS-классы) и бизнес-логику состояния (модель данных) для предотвращения конфликтов.
  • Для сложных интерфейсов создавать модули управления состоянием, которые обрабатывают события и синхронизируют DOM и данные.

Эти подходы делают управление состоянием в Shopify Draggable гибким, предсказуемым и легко расширяемым для любых интерфейсов.