Система событий библиотеки

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

Подключение обработчиков событий

Объект Draggable предоставляет метод .on(eventName, callback), с помощью которого можно подписаться на определённое событие. Пример:

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

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

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

  • eventName — строка с названием события.
  • callback — функция, принимающая объект события с информацией о целевом элементе, контейнере и положении курсора.
  • Подписка может быть множественной: на одно событие можно повесить несколько обработчиков.

Основные события

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

  1. Drag события – касаются начала, движения и завершения перетаскивания.

    • drag:start — срабатывает при начале перетаскивания элемента.
    • drag:move — срабатывает при каждом изменении позиции элемента.
    • drag:stop — срабатывает после завершения перетаскивания.
  2. Sortable события – связаны с изменением порядка элементов.

    • sortable:sort — вызывается при перемещении элемента относительно других.
    • sortable:sorted — фиксирует окончательное положение элемента после сортировки.
  3. Mirror события – относятся к визуальному отражению перетаскиваемого элемента (mirror element).

    • mirror:create — когда создаётся зеркало элемента для перетаскивания.
    • mirror:destroy — когда зеркало удаляется после завершения перетаскивания.

Структура объекта события

Объект, передаваемый в обработчик, содержит важные свойства:

  • source — DOM-элемент, который перетаскивается.
  • container — контейнер, из которого происходит перетаскивание.
  • originalEvent — исходное событие мыши или тач.
  • mirror — DOM-элемент зеркала (если используется).
  • oldIndex и newIndex — индексы элемента до и после сортировки (для sortable).

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

draggable.on('sortable:sorted', (event) => {
  console.log(`Элемент ${event.source.textContent} перемещён с позиции ${event.oldIndex} на ${event.newIndex}`);
});

Удаление обработчиков

Для управления подписками существует метод .off(eventName, callback), который удаляет конкретный обработчик. Это особенно важно при динамическом создании и уничтожении Draggable-объектов.

function onDragStart(event) {
  console.log('Начало перетаскивания:', event.source);
}

draggable.on('drag:start', onDragStart);

// позже
draggable.off('drag:start', onDragStart);

Если вызвать .off(eventName) без второго параметра, удаляются все обработчики данного события.

Настройка событий через опции

Некоторые события могут быть настроены при инициализации Draggable через объект опций, например, отключение зеркала:

const draggable = new Draggable(document.querySelectorAll('.list-item'), {
  draggable: '.item',
  mirror: {
    constrainDimensions: true
  }
});

Взаимодействие нескольких Draggable экземпляров

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

const listA = new Draggable(document.querySelectorAll('.list-a'), { draggable: '.item' });
const listB = new Draggable(document.querySelectorAll('.list-b'), { draggable: '.item' });

listA.on('sortable:sorted', (event) => {
  console.log('Элемент перемещён в listA', event.source);
});

listB.on('sortable:sorted', (event) => {
  console.log('Элемент перемещён в listB', event.source);
});

Прерывание событий

Draggable позволяет отменить стандартное поведение событий с помощью метода event.cancel(). Например, можно запретить перемещение некоторых элементов:

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

Это обеспечивает гибкий контроль над логикой перетаскивания, позволяя создавать сложные интерфейсы с ограничениями.

Встроенные вспомогательные события

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

  • drag:over — когда элемент проходит над контейнером.
  • drag:out — когда элемент покидает контейнер.
  • drag:pressure — измерение силы нажатия (для устройств с поддержкой Force Touch).

Использование этих событий позволяет реализовать динамическое взаимодействие с пользователем и анимации, зависящие от позиции курсора.

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

  • Подписки на события должны быть минимальными: тяжелые вычисления лучше выполнять через requestAnimationFrame.
  • Использовать event.cancel() для исключения ненужных перемещений, это снижает нагрузку на DOM.
  • Разделять обработчики для разных контейнеров для удобного логирования и отладки.

Система событий Shopify Draggable предоставляет полный набор инструментов для контроля поведения элементов, позволяя реализовать любые сценарии перетаскивания, сортировки и взаимодействия с интерфейсом.