onAdd и onRemove

SortableJS предоставляет мощные возможности для реализации интерактивного перетаскивания элементов в списках. Два ключевых события, позволяющих управлять логикой после перемещения элементов, — это onAdd и onRemove. Они применяются в ситуациях, когда элементы перемещаются между списками, а также при добавлении или удалении элементов из DOM через взаимодействие пользователя.


Событие onAdd

onAdd срабатывает, когда элемент был перенесён из другого списка и вставлен в текущий. Это событие полезно для синхронизации состояния данных при перемещении элементов между различными контейнерами.

Пример использования:

const list = document.getElementById('sortable-list');

Sortable.create(list, {
  group: 'shared', // объединяет списки в одну группу для перемещения
  animation: 150,
  onAdd: function (evt) {
    const item = evt.item; // DOM-элемент, который был добавлен
    const newIndex = evt.newIndex; // индекс в новом списке
    console.log(`Элемент добавлен: ${item.textContent} на позицию ${newIndex}`);
    
    // Обновление модели данных
    data.splice(newIndex, 0, item.dataset.id);
  }
});

Ключевые свойства объекта события evt:

  • evt.item — DOM-элемент, который был добавлен.
  • evt.from — исходный контейнер, откуда элемент был перемещён.
  • evt.to — новый контейнер, в который элемент помещён.
  • evt.oldIndex — индекс элемента в исходном списке.
  • evt.newIndex — индекс элемента в новом списке.
  • evt.clone — клонированный элемент при использовании pull: 'clone'.

Особенности использования:

  • Группы (group): чтобы событие onAdd срабатывало при перемещении элементов, списки должны быть объединены в группу. Значение group может быть строкой или объектом с параметрами name, pull, put.
  • Обновление данных: после перетаскивания важно синхронизировать массивы или объекты, содержащие данные элементов. onAdd позволяет вставить новый элемент в массив по evt.newIndex.

Событие onRemove

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

Пример:

Sortable.create(list, {
  group: 'shared',
  animation: 150,
  onRemove: function (evt) {
    const removedItem = evt.item;
    const oldIndex = evt.oldIndex;
    console.log(`Элемент удалён: ${removedItem.textContent} с позиции ${oldIndex}`);
    
    // Обновление модели данных
    data.splice(oldIndex, 1);
  }
});

Свойства объекта evt, используемые в onRemove:

  • evt.item — удалённый DOM-элемент.
  • evt.from — контейнер, из которого элемент был удалён.
  • evt.oldIndex — индекс элемента в исходном списке.
  • evt.clone — клонированный элемент, если использовалось клонирование.

Особенности использования:

  • onRemove и onAdd часто используются совместно, когда требуется полностью перенести элемент из одного массива данных в другой.
  • Если элемент удаляется, но остаётся в DOM (например, при клонировании), необходимо использовать evt.clone для обработки копии.

Взаимодействие onAdd и onRemove

При перемещении элемента между списками с включёнными событиями onAdd и onRemove, порядок срабатывания следующий:

  1. onRemove срабатывает в исходном списке — удаление элемента из массива данных или визуального списка.
  2. onAdd срабатывает в целевом списке — вставка элемента на новую позицию.

Пример синхронизации двух массивов:

const listA = document.getElementById('list-a');
const listB = document.getElementById('list-b');

const dataA = ['a1', 'a2', 'a3'];
const dataB = ['b1', 'b2', 'b3'];

Sortable.create(listA, {
  group: 'shared',
  onAdd: function(evt) {
    const itemId = evt.item.dataset.id;
    dataA.splice(evt.newIndex, 0, itemId);
  },
  onRemove: function(evt) {
    dataA.splice(evt.oldIndex, 1);
  }
});

Sortable.create(listB, {
  group: 'shared',
  onAdd: function(evt) {
    const itemId = evt.item.dataset.id;
    dataB.splice(evt.newIndex, 0, itemId);
  },
  onRemove: function(evt) {
    dataB.splice(evt.oldIndex, 1);
  }
});

Такое сочетание гарантирует, что массивы dataA и dataB полностью соответствуют визуальному состоянию списков после всех перемещений.


Дополнительные параметры

  • evt.clone используется при настройке pull: 'clone', когда элемент копируется вместо перемещения.
  • evt.pullMode указывает, была ли операция копированием или перемещением.
  • События onAdd и onRemove могут использоваться с store для автоматического сохранения состояния списков в localStorage.

Советы по эффективному использованию

  • События должны работать с массивами или объектами, а не напрямую с DOM, для сохранения структуры данных.
  • Для сложных интерфейсов с несколькими списками рекомендуется централизованная обработка onAdd/onRemove через одну функцию, чтобы уменьшить дублирование кода.
  • Использование анимации (animation) улучшает визуальное восприятие перемещения, но не влияет на работу onAdd и onRemove.

Если требуется, могу дополнительно написать подробный пример перетаскивания с клонированием и синхронизацией нескольких массивов, где onAdd и onRemove используются в связке с drag-and-drop между тремя списками. Это покажет полный спектр возможностей SortableJS.