Декораторы событий

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


Основные принципы работы

Декораторы событий в Draggable применяются через методы on, off и once, которые позволяют подписываться на события, отписываться от них и выполнять обработчики один раз соответственно.

  • on(eventName, callback) — привязывает обработчик к событию.
  • off(eventName, callback) — удаляет обработчик.
  • once(eventName, callback) — привязывает обработчик, который выполнится один раз и автоматически отписывается после первого срабатывания.

События в Draggable можно разделить на несколько категорий:

  1. События перетаскивания (drag lifecycle):

    • drag:start — начало перетаскивания элемента.
    • drag:move — движение элемента во время перетаскивания.
    • drag:stop — завершение перетаскивания.
  2. События сортировки (sort lifecycle):

    • sortable:sorted — элемент был успешно перемещён в новое место.
    • sortable:stop — завершение процесса сортировки.
  3. События уведомлений и ошибки:

    • drag:over — элемент перемещён над другой областью.
    • drag:out — элемент покидает область.

Пример привязки событий

import { Draggable } from '@shopify/draggable';

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

// Привязка событий с использованием on
draggable.on('drag:start', (event) => {
  console.log('Начало перетаскивания:', event.source);
});

draggable.on('drag:move', (event) => {
  console.log('Элемент перемещается:', event.source);
});

draggable.on('drag:stop', (event) => {
  console.log('Перетаскивание завершено:', event.source);
});

В этом примере event.source содержит ссылку на HTML-элемент, который перетаскивается, а объект события предоставляет дополнительные свойства, такие как координаты мыши, текущее состояние и контейнеры.


Использование once и off

Метод once применяется, когда нужно выполнить обработку события только один раз:

draggable.once('drag:start', (event) => {
  console.log('Эта функция выполнится только один раз при первом перетаскивании');
});

Метод off позволяет динамически отключать обработчики:

function handleDragStop(event) {
  console.log('Перетаскивание остановлено', event.source);
}

// Подключаем обработчик
draggable.on('drag:stop', handleDragStop);

// Позже отключаем обработчик
draggable.off('drag:stop', handleDragStop);

Работа с делегированными событиями

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

const draggable = new Draggable(document.body, {
  draggable: '.draggable-item',
  delay: 200
});

draggable.on('drag:start', (event) => {
  if (event.source.matches('.important-item')) {
    console.log('Начало перетаскивания важного элемента');
  }
});

Здесь проверка event.source.matches() позволяет фильтровать события и реагировать только на определённые элементы.


Передача дополнительных данных через события

Объект события содержит свойства, которые можно использовать для передачи данных между обработчиками:

  • event.source — элемент, с которого началось перетаскивание.
  • event.sensorEvent — исходное событие мыши или касания.
  • event.over — элемент, над которым находится перетаскиваемый объект.
  • event.draggable — экземпляр Draggable.

Пример использования данных события для кастомизации поведения:

draggable.on('drag:over', (event) => {
  const overElement = event.over;
  if (overElement && overElement.classList.contains('highlight-zone')) {
    overElement.style.backgroundColor = 'yellow';
  }
});

draggable.on('drag:out', (event) => {
  const outElement = event.over;
  if (outElement) {
    outElement.style.backgroundColor = '';
  }
});

Комплексная обработка событий

Можно объединять события для реализации сложной логики сортировки и перетаскивания:

draggable.on('drag:start', (event) => {
  event.source.classList.add('dragging');
});

draggable.on('drag:stop', (event) => {
  event.source.classList.remove('dragging');
});

draggable.on('sortable:sorted', (event) => {
  const newIndex = Array.from(event.container.children).indexOf(event.source);
  console.log('Элемент перемещён на позицию', newIndex);
});

В этом примере добавление и удаление класса dragging визуально отображает состояние элемента, а событие sortable:sorted позволяет отслеживать конечное положение элемента после сортировки.


Рекомендации по организации событий

  1. Использовать once для одноразовых действий, таких как инициализация.
  2. Использовать off для динамического удаления обработчиков при изменении DOM.
  3. Делегировать события на контейнер, чтобы уменьшить количество подписок.
  4. Проверять event.source и event.over для фильтрации элементов.
  5. Разделять обработку drag и sortable для упрощения логики.

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