Сложные сценарии

SortableJS — это мощная библиотека для реализации перетаскивания элементов на веб-странице. Основной способ её подключения — через CDN или пакетный менеджер. После подключения создается новый экземпляр Sortable, передавая в конструктор контейнер и объект с опциями:

import Sortable from 'sortablejs';

const list = document.getElementById('items');
const sortable = new Sortable(list, {
    animation: 150,
    handle: '.handle',
    draggable: '.item',
});

Ключевые параметры:

  • animation — плавность перемещения элементов.
  • handle — указание области, за которую возможно перетаскивание.
  • draggable — селектор элементов, которые можно перемещать.

Работа с несколькими списками

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

const sortable1 = new Sortable(list1, {
    group: 'shared',
    animation: 200,
});
const sortable2 = new Sortable(list2, {
    group: 'shared',
    animation: 200,
});

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

  • name — идентификатор группы.
  • pull — разрешает или запрещает вынос элементов из списка.
  • put — разрешает или запрещает прием элементов из других списков.

Гибкое использование pull и put позволяет создавать сложные сценарии, например, односторонние списки, где элементы можно только перетаскивать в один контейнер.


Работа с событиями

SortableJS предоставляет широкий набор событий, которые позволяют отслеживать все этапы взаимодействия:

  • onStart — начало перетаскивания.
  • onEnd — завершение перетаскивания.
  • onAdd — элемент добавлен в другой список.
  • onUpdate — элемент перемещен внутри текущего списка.
  • onRemove — элемент удален из текущего списка.
  • onSort — любое изменение порядка элементов.

Пример обработки событий:

const sortable = new Sortable(list, {
    animation: 150,
    onEnd: function (evt) {
        console.log(`Элемент перемещен с позиции ${evt.oldIndex} на ${evt.newIndex}`);
    },
});

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


Кастомизация перетаскивания

SortableJS поддерживает детальную настройку поведения элементов:

  • sort — включает или отключает сортировку элементов внутри контейнера.
  • filter — задает элементы, которые нельзя перемещать.
  • preventOnFilter — предотвращает действие браузера на фильтрованных элементах.
  • ghostClass — CSS-класс для копии перетаскиваемого элемента.
  • chosenClass — CSS-класс для выбранного элемента.

Пример фильтрации:

const sortable = new Sortable(list, {
    filter: '.non-draggable',
    preventOnFilter: false,
});

Элементы с классом .non-draggable не будут перемещаться, при этом другие элементы останутся интерактивными.


Сложные сценарии с копированием и клонированием

Иногда необходимо, чтобы элемент при перетаскивании оставался в исходном списке и одновременно создавал копию в другом. Для этого используется функция clone и pull: 'clone' в группе:

const sortableSource = new Sortable(listSource, {
    group: {
        name: 'clone-group',
        pull: 'clone',
        put: false,
    },
    animation: 150,
});
const sortableTarget = new Sortable(listTarget, {
    group: 'clone-group',
    animation: 150,
});

Этот подход подходит для реализации функционала «добавить элемент в корзину», когда оригинал остается на месте, а копия добавляется в другой контейнер.


Динамическое добавление и удаление элементов

SortableJS корректно работает с динамическим изменением DOM. Если элементы создаются или удаляются после инициализации, достаточно обновить список вызовом метода sort() или просто позволить библиотеке работать с новыми элементами через draggable селектор.

const newItem = document.createElement('li');
newItem.className = 'item';
newItem.textContent = 'Новый элемент';
list.appendChild(newItem);

После добавления элемент автоматически станет перетаскиваемым, если селектор совпадает с draggable.


Поддержка вложенных списков

Для реализации вложенных сортируемых списков (nested lists) можно использовать отдельные экземпляры Sortable для каждого уровня:

const parentSortable = new Sortable(parentList, {
    group: 'nested',
    animation: 150,
});
const childSortable = new Sortable(childList, {
    group: 'nested',
    animation: 150,
});

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


Интеграция с фронтенд-фреймворками

SortableJS хорошо интегрируется с Vue, React и Angular через официальные обертки или нативные методы. Для React, например, используется компонент SortableContainer и SortableElement:

import { SortableContainer, SortableElement } from 'react-sortablejs';

const SortableItem = SortableElement(({ value }) => <li>{value}</li>);
const SortableList = SortableContainer(({ items }) => (
    <ul>
        {items.map((value, index) => (
            <SortableItem key={index} index={index} value={value} />
        ))}
    </ul>
));

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


Производительность и оптимизация

Для больших списков важно учитывать производительность. Рекомендации:

  • Использовать animation с минимальной задержкой для плавного перемещения.
  • Фильтровать элементы с помощью filter вместо удаления из DOM.
  • Ограничивать количество перетаскиваемых элементов через селекторы draggable.
  • Минимизировать обработку событий onMove и onUpdate, особенно если они запускают тяжелые вычисления или запросы к серверу.

Эти меры обеспечивают стабильную работу интерфейса даже при сотнях элементов и сложных сценариях взаимодействия.