Для работы с библиотекой Shopify Draggable необходимо установить пакет через npm или подключить через CDN. При установке через npm используется команда:
npm install @shopify/draggable
Подключение в проекте выглядит следующим образом:
import { Sortable, Swappable, Droppable } from '@shopify/draggable';
Для CDN:
<script src="https://cdn.jsdelivr.net/npm/@shopify/draggable@1.0.0-beta.8/lib/draggable.bundle.js"></script>
После подключения библиотека готова к созданию перетаскиваемых элементов и обработке событий.
Sortable позволяет перемещать элементы внутри контейнера и отслеживать изменения порядка:
const sortable = new Sortable(document.querySelectorAll('.draggable-list'), {
draggable: '.draggable-item',
mirror: {
constrainDimensions: true
}
});
Draggable предоставляет мощный механизм событий для отслеживания действий пользователя. Основные события для отправки данных на сервер:
Пример подписки на событие окончания сортировки:
sortable.on('sortable:stop', (event) => {
const items = [...event.data.container.children];
const order = items.map((item, index) => ({
id: item.dataset.id,
position: index + 1
}));
sendOrderToServer(order);
});
После перетаскивания важно собрать актуальный порядок элементов. Чаще всего используется массив объектов с идентификатором и позицией:
function getOrder(container) {
return Array.from(container.children).map((item, index) => ({
id: item.dataset.id,
position: index + 1
}));
}
Эта структура удобна для передачи в JSON и обработки на серверной стороне.
Для отправки на сервер используется современный Fetch API. В примере отправка нового порядка элементов:
function sendOrderToServer(order) {
fetch('/update-order', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ order })
})
.then(response => response.json())
.then(data => console.log('Порядок сохранен', data))
.catch(error => console.error('Ошибка при сохранении', error));
}
Особенности:
На серверной стороне можно использовать Express для обработки запроса:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.post('/update-order', (req, res) => {
const order = req.body.order;
// Логика обновления в базе данных
console.log('Получен новый порядок:', order);
res.json({ success: true });
});
app.listen(3000, () => console.log('Сервер запущен на порту 3000'));
Перед отправкой на сервер рекомендуется проверять данные:
function validateOrder(order) {
return order.every(item => item.id && Number.isInteger(item.position));
}
Пример отправки только валидного порядка:
if (validateOrder(order)) {
sendOrderToServer(order);
} else {
console.error('Некорректные данные для отправки');
}
Если элементы часто перетаскиваются, имеет смысл использовать debounce, чтобы не перегружать сервер:
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
const sendOrderDebounced = debounce(sendOrderToServer, 300);
sortable.on('sortable:stop', (event) => {
const order = getOrder(event.data.container);
sendOrderDebounced(order);
});
Это позволяет объединять быстрые действия пользователя и отправлять изменения на сервер с интервалом 300 мс.
Если на странице несколько зон перетаскивания, можно собрать данные из всех контейнеров:
function getAllOrders(containers) {
return containers.map(container => ({
containerId: container.dataset.id,
items: getOrder(container)
}));
}
sortable.on('sortable:stop', () => {
const orders = getAllOrders(document.querySelectorAll('.draggable-list'));
sendOrderToServer(orders);
});
Такая организация упрощает работу с множеством списков и позволяет серверу получать полную информацию о состоянии интерфейса.
Для защищенных API можно передавать токен:
fetch('/update-order', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({ order })
});
Это обеспечит корректную проверку прав пользователя на изменение порядка элементов.
После успешного запроса можно визуально подтвердить пользователю, что изменения сохранены:
.then(data => {
if (data.success) {
document.querySelector('#status').textContent = 'Порядок сохранен';
}
});
Сочетание Shopify Draggable, правильной обработки событий и надежной отправки данных обеспечивает гибкое и интерактивное управление списками на фронтенде с сохранением состояния на сервере.