SortableJS — это легковесная библиотека для реализации drag-and-drop интерфейсов в JavaScript. Одной из ключевых возможностей при работе с динамическими списками является синхронизация изменений с внешними хранилищами данных, такими как серверная база, локальное хранилище браузера или облачные сервисы.
Синхронизация требует отслеживания изменений состояния элементов списка и передачи этих изменений в выбранное хранилище. Ключевые моменты:
onEnd, onAdd,
onUpdate, onRemove), которые позволяют
фиксировать момент завершения перетаскивания элементов.data-id или свойство объекта в
массиве.Основное событие для синхронизации — onEnd. Оно
срабатывает после завершения перетаскивания элемента. Пример
обработки:
const list = document.getElementById('items');
Sortable.create(list, {
animation: 150,
onEnd: function (evt) {
const itemEl = evt.item;
const oldIndex = evt.oldIndex;
const newIndex = evt.newIndex;
updateStorage(itemEl.dataset.id, oldIndex, newIndex);
}
});
function updateStorage(id, oldIndex, newIndex) {
// пример обновления на сервере
fetch('/update-item-position', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id, oldIndex, newIndex })
});
}
В этом примере происходит:
evt.item).Если список представлен массивом JavaScript, синхронизация может происходить напрямую:
let items = [
{ id: 1, name: 'Элемент 1' },
{ id: 2, name: 'Элемент 2' },
{ id: 3, name: 'Элемент 3' }
];
Sortable.create(document.getElementById('items'), {
animation: 150,
onEnd: function (evt) {
const [movedItem] = items.splice(evt.oldIndex, 1);
items.splice(evt.newIndex, 0, movedItem);
}
});
Такой подход позволяет поддерживать актуальное состояние массива без лишних операций. Он особенно полезен для последующего сериализованного сохранения в хранилище.
Для сохранения состояния списка между сессиями можно использовать
localStorage:
function saveToLocalStorage(items) {
localStorage.setItem('sortableItems', JSON.stringify(items));
}
function loadFromLocalStorage() {
const stored = localStorage.getItem('sortableItems');
return stored ? JSON.parse(stored) : [];
}
let items = loadFromLocalStorage();
Sortable.create(document.getElementById('items'), {
animation: 150,
onEnd: function (evt) {
const [movedItem] = items.splice(evt.oldIndex, 1);
items.splice(evt.newIndex, 0, movedItem);
saveToLocalStorage(items);
}
});
Использование локального хранилища гарантирует, что порядок элементов сохраняется даже после обновления страницы.
При работе с удалёнными серверами рекомендуется:
fetch или Axios.Пример пакетной отправки:
let changedItems = [];
Sortable.create(document.getElementById('items'), {
animation: 150,
onEnd: function (evt) {
const [movedItem] = items.splice(evt.oldIndex, 1);
items.splice(evt.newIndex, 0, movedItem);
changedItems.push({ id: movedItem.id, newIndex: evt.newIndex });
if (changedItems.length > 5) {
syncWithServer(changedItems);
changedItems = [];
}
}
});
function syncWithServer(changes) {
fetch('/sync-items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(changes)
});
}
SortableJS поддерживает возможность объединения нескольких списков в
одну группу через опцию group. Это позволяет
синхронизировать перемещения между списками:
Sortable.create(document.getElementById('list1'), { group: 'shared', animation: 150 });
Sortable.create(document.getElementById('list2'), { group: 'shared', animation: 150 });
При этом важно обрабатывать события onAdd и
onRemove для корректного обновления внешнего хранилища:
onAdd: function(evt) {
const movedItem = evt.item;
addItemToStorage(evt.to.id, movedItem.dataset.id, evt.newIndex);
},
onRemove: function(evt) {
removeItemFromStorage(evt.from.id, evt.item.dataset.id);
}
Для удобства можно сериализовать весь список в виде JSON, что облегчает интеграцию с внешними хранилищами:
function serializeList(listEl) {
return Array.from(listEl.children).map(el => el.dataset.id);
}
Сериализованный массив может быть сразу сохранён на сервере или в локальном хранилище.