SortableJS — это мощная библиотека для создания интерактивных списков с поддержкой перетаскивания элементов. Одной из ключевых особенностей при интеграции с современными фреймворками является обеспечение реактивности и корректного обновления состояния списка после изменений.
В реактивных фреймворках, таких как Vue или React, состояние элементов часто хранится в массивах. SortableJS по умолчанию управляет DOM-элементами, но не реактивным массивом напрямую. Для корректного взаимодействия необходимо синхронизировать события библиотеки с массивом данных.
Пример базового связывания с массивом:
import Sortable from 'sortablejs';
const items = ['Элемент 1', 'Элемент 2', 'Элемент 3'];
const listElement = document.getElementById('sortable-list');
Sortable.create(listElement, {
animation: 150,
onEnd: (evt) => {
const [movedItem] = items.splice(evt.oldIndex, 1);
items.splice(evt.newIndex, 0, movedItem);
}
});
Ключевые моменты:
onEnd вызывается после завершения перетаскивания.items обновляется в точном соответствии с
изменениями DOM.splice используется для удаления и вставки элемента,
обеспечивая сохранение порядка элементов.Если элементы списка изменяются динамически (например, добавляются
или удаляются новые элементы), необходимо обновлять экземпляр
SortableJS с помощью метода destroy() и
последующего повторного создания, либо использовать
Sortable.update().
// Обновление после добавления нового элемента
items.push('Новый элемент');
listElement.innerHTML = items.map(item => `<li>${item}</li>`).join('');
sortableInstance.destroy();
sortableInstance = Sortable.create(listElement, {
animation: 150,
onEnd: (evt) => {
const [movedItem] = items.splice(evt.oldIndex, 1);
items.splice(evt.newIndex, 0, movedItem);
}
});
Особенности:
В Vue 3 с Composition API управление списком можно сделать более «нативным»:
import { ref, onMounted } from 'vue';
import Sortable from 'sortablejs';
export default {
setup() {
const items = ref(['Элемент A', 'Элемент B', 'Элемент C']);
let sortableInstance;
onMounted(() => {
sortableInstance = Sortable.create(document.getElementById('sortable-list'), {
animation: 150,
onEnd: (evt) => {
const [moved] = items.value.splice(evt.oldIndex, 1);
items.value.splice(evt.newIndex, 0, moved);
}
});
});
return { items };
}
}
Примечания по реактивности:
ref позволяет Vue автоматически
отслеживать изменения массива.items.value синхронизируется с DOM, поддерживая
реактивность интерфейса.onEnd гарантирует, что порядок элементов в
массиве и на экране совпадает.Для списков с сотнями элементов рекомендуется:
animation: 0 при частых обновлениях, чтобы
избежать задержек рендеринга.destroy и create только при
необходимости.virtual-scroll), чтобы Sortable работал только с видимыми
элементами.SortableJS поддерживает группы элементов, что позволяет перетаскивать объекты между списками. Для реактивного управления требуется двусторонняя синхронизация массивов.
const listA = ['A1', 'A2'];
const listB = ['B1', 'B2'];
Sortable.create(document.getElementById('list-a'), {
group: 'shared',
onAdd: (evt) => {
const [item] = listB.splice(evt.oldIndex, 1);
listA.splice(evt.newIndex, 0, item);
}
});
Sortable.create(document.getElementById('list-b'), {
group: 'shared',
onAdd: (evt) => {
const [item] = listA.splice(evt.oldIndex, 1);
listB.splice(evt.newIndex, 0, item);
}
});
Особенности синхронизации:
onAdd вызывается при добавлении элемента из другой
группы.onUpdate используется, если требуется
обработка изменений без удаления элемента.onMove позволяет предотвратить
перемещение по условию.Эффективное использование SortableJS в реактивных приложениях требует
внимательного контроля синхронизации между массивами данных и DOM.
Корректная реализация событий onEnd, onAdd,
onUpdate позволяет создать интерактивный,
устойчивый и масштабируемый интерфейс перетаскивания
элементов.