Я работаю над приложением визуального программирования, которое имеет два столбца.
Столбец слева представляет собой набор инструментов, из которого пользователи могут перетаскивать «элементы» в столбец справа, который представляет собой сценарий, который пользователь может собрать. Визуально это выглядит как этот пример.
Я пытаюсь реализовать это в Svelte. В каждой из двух моих колонок есть раздел each
для заполнения его элементами.
У меня возникли трудности с перетаскиванием на работу с помощью svelte-dnd-action
.
Во-первых, кажется, что эта библиотека предполагает, что когда вы перетаскиваете что-то куда-то еще, вы перемещаете этот элемент. Из-за этого ящик с инструментами со временем становится пустым, когда я вытаскиваю из него что-то. Итак, моя первая проблема заключается в том, что мне нужно найти способ клонировать элемент, когда пользователи начинают его вытаскивать.
Еще одна менее серьезная вещь, которую я считаю неудобной, — это то, что все должно иметь идентификатор. Сейчас оба столбца загружаются из содержимого JSON при загрузке страницы. В итоге я написал функцию-обходчик, которая обходит проанализированные объекты и присваивает uuid всем элементам. Затем при перетаскивании я пытался клонировать и рекурсивно восстанавливать идентификаторы перетаскиваемого элемента.
Я пробовал различные «обратные вызовы» on:consider
, on:finalize
и т. д., но их настройка почти такая же, как если бы перетаскивание уже было выполнено (они добавляют элемент в конец списка).
Я получал различные ошибки, связанные с идентификаторами (элементы в each
должны быть уникальными), вплоть до старой доброй ошибки «ничего не происходит», когда я могу инициировать действие перетаскивания, но перетаскиваемый элемент не принимается на другом конце. .
Как я могу заставить это работать? При необходимости я бы рассмотрел возможность перехода на другую библиотеку перетаскивания.
🤔 А знаете ли вы, что...
JavaScript используется для разработки современных одностраничных приложений (SPA), где весь контент загружается асинхронно.
В документации есть список примеров , один показывает, как элементы можно копировать при перетаскивании.
Код обработчика для копирования, но не в список источников:
import { dndzone, TRIGGERS, SHADOW_ITEM_MARKER_PROPERTY_NAME } from 'svelte-dnd-action';
// ...
let shouldIgnoreDndEvents = false;
function handleDndConsider(e) {
const {trigger, id} = e.detail.info;
if (trigger === TRIGGERS.DRAG_STARTED) {
const idx = items.findIndex(item => item.id === id);
const newId = `${id}_copy_${Math.round(Math.random() * 100000)}`;
// the line below was added in order to be compatible with version svelte-dnd-action 0.7.4 and above
e.detail.items = e.detail.items.filter(item => !item[SHADOW_ITEM_MARKER_PROPERTY_NAME]);
e.detail.items.splice(idx, 0, { ...items[idx], id: newId });
items = e.detail.items;
shouldIgnoreDndEvents = true;
}
else if (!shouldIgnoreDndEvents) {
items = e.detail.items;
}
else {
items = [...items];
}
}
function handleDndFinalize(e) {
if (!shouldIgnoreDndEvents) {
items = e.detail.items;
}
else {
items = [...items];
shouldIgnoreDndEvents = false;
}
}
При этом выполняется поверхностное копирование через распространение и присваивается новый идентификатор. Если предмет глубже или сложнее, вам может понадобиться более сложная логика.