Связь DOM и модели данных

SortableJS — это библиотека для организации интерактивной сортировки элементов HTML с помощью drag-and-drop. Она позволяет динамически изменять порядок элементов в DOM и автоматически синхронизировать эти изменения с моделью данных, что делает её особенно удобной для создания списков, таблиц и интерактивных интерфейсов.

Библиотека работает на чистом JavaScript без зависимостей, но её легко интегрировать с фреймворками вроде React, Vue или Angular, где требуется синхронизация состояния интерфейса с данными.


Инициализация и базовое использование

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

<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

После этого можно инициализировать сортируемый контейнер:

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

const sortable = new Sortable(list, {
    animation: 150,  // плавная анимация перемещения
    ghostClass: 'sortable-ghost', // класс для элемента, который тянется
});

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

  • animation — скорость анимации перетаскивания в миллисекундах.
  • ghostClass — CSS-класс для визуального эффекта перетаскиваемого элемента.
  • handle — селектор, определяющий область, за которую можно тянуть элемент.
  • draggable — селектор элементов внутри контейнера, которые можно перетаскивать.

События SortableJS

События позволяют синхронизировать порядок в DOM с моделью данных. Основные события:

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

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

let items = ['Яблоко', 'Банан', 'Апельсин'];

const sortable = new Sortable(list, {
    animation: 150,
    onEnd: function (evt) {
        const movedItem = items.splice(evt.oldIndex, 1)[0];
        items.splice(evt.newIndex, 0, movedItem);
        console.log(items);
    }
});

Здесь evt.oldIndex и evt.newIndex указывают на старую и новую позиции элемента в DOM, что позволяет точно обновить модель данных.


Связь DOM и модели данных

SortableJS изменяет порядок элементов в DOM, но для полноценного использования нужно синхронизировать изменения с внутренними структурами данных. Важно учитывать:

  • Индексация элементов: порядок в DOM напрямую соответствует индексам в массиве данных.
  • Использование data-* атрибутов: для привязки элементов к объектам данных удобно хранить идентификаторы через data-id.
  • Обновление сложных структур: если список содержит объекты, а не строки, можно использовать find по id для точной перестановки элементов.

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

let tasks = [
    { id: 1, title: 'Сделать задачу A' },
    { id: 2, title: 'Сделать задачу B' },
    { id: 3, title: 'Сделать задачу C' }
];

const sortable = new Sortable(list, {
    animation: 150,
    onEnd: function (evt) {
        const [movedTask] = tasks.splice(evt.oldIndex, 1);
        tasks.splice(evt.newIndex, 0, movedTask);
    }
});

Использование data-id для идентификации:

<li data-id="1">Сделать задачу A</li>
<li data-id="2">Сделать задачу B</li>
<li data-id="3">Сделать задачу C</li>
const movedTaskId = parseInt(evt.item.dataset.id, 10);

Расширенные возможности

  • Сортировка между несколькими списками: параметр group позволяет перетаскивать элементы между разными контейнерами:
new Sortable(list1, { group: 'shared' });
new Sortable(list2, { group: 'shared' });
  • Фильтрация элементов: filter позволяет запретить перетаскивание определённых элементов:
new Sortable(list, {
    filter: '.no-drag',
    onMove: function(evt) {
        return !evt.related.classList.contains('no-drag');
    }
});
  • Поддержка touch и мобильных устройств: встроенная обработка touchstart, touchmove и touchend делает библиотеку кроссплатформенной.

  • Анимация и визуальные эффекты: ghostClass, chosenClass и CSS-переходы позволяют создавать плавное визуальное взаимодействие, повышающее удобство интерфейса.


Синхронизация с фреймворками

Для работы с React, Vue или Angular важно разделять DOM-манипуляции и управление состоянием. SortableJS предоставляет хуки, позволяющие:

  • получать событие перестановки (onEnd),
  • изменять массив состояния данных,
  • инициировать повторный рендер компонентов на основе обновлённого массива.

Пример для Vue:

<template>
  <ul ref="list">
    <li v-for="task in tasks" :key="task.id">{{ task.title }}</li>
  </ul>
</template>

<script>
import Sortable from 'sortablejs';

export default {
  data() {
    return { tasks: [...] };
  },
  mounted() {
    Sortable.create(this.$refs.list, {
      onEnd: evt => {
        const moved = this.tasks.splice(evt.oldIndex, 1)[0];
        this.tasks.splice(evt.newIndex, 0, moved);
      }
    });
  }
};
</script>

Практические рекомендации

  • Всегда поддерживать синхронизацию DOM и данных через события onEnd или onUpdate.
  • Использовать data-id для стабильной идентификации элементов.
  • Для больших списков включать animation и forceFallback для улучшенной производительности на мобильных устройствах.
  • Комбинировать с CSS для визуальной индикации перемещаемого элемента, чтобы пользователи точно понимали текущую операцию.

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