Lazy loading при перетаскивании заключается в динамическом создании или подгрузке элементов в момент их взаимодействия с пользователем, а не заранее при инициализации страницы. Это особенно полезно для интерфейсов с большим количеством draggable- или resizable-элементов, когда рендер всех элементов сразу приводит к значительной нагрузке на DOM и ухудшению производительности.
В Interact.js для реализации lazy loading используют события
перетаскивания (dragstart, dragmove) и
возможность динамического создания DOM-элементов прямо в обработчиках
событий.
Прежде всего необходимо подключить библиотеку и определить базовую конфигурацию для элементов:
interact('.draggable')
.draggable({
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
listeners: {
start(event) { onDragStart(event); },
move(event) { onDragMove(event); },
end(event) { onDragEnd(event); }
}
});
Здесь ключевое внимание уделяется listeners, где будут
обрабатываться события, необходимые для lazy loading.
dragstartLazy loading часто подразумевает, что элементы создаются только в момент начала перетаскивания. Это минимизирует количество элементов в DOM до момента их использования:
function onDragStart(event) {
const target = event.target;
if (!target.dataset.loaded) {
const newItem = document.createElement('div');
newItem.className = 'draggable-item';
newItem.textContent = 'Новый элемент';
target.appendChild(newItem);
target.dataset.loaded = true;
}
}
dataset.loaded используется для предотвращения
повторного создания элементов при последующих drag-сессиях.dragstart гарантирует,
что он будет полностью готов к перетаскиванию без предварительного
рендера.dragmove для подгрузки данныхВ некоторых случаях элементы могут быть визуально уже на странице, но содержимое, например изображения или сложные компоненты, подгружается только во время перетаскивания. Это позволяет уменьшить первоначальную загрузку страницы:
function onDragMove(event) {
const target = event.target;
const rect = target.getBoundingClientRect();
// Подгрузка данных при попадании элемента в область видимости
if (!target.dataset.contentLoaded && rect.top < window.innerHeight) {
fetch('/api/item-content/' + target.dataset.id)
.then(response => response.text())
.then(content => {
target.innerHTML = content;
target.dataset.contentLoaded = true;
});
}
// Обновление позиции
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
Ключевые моменты:
contentLoaded) позволяет
экономить сетевые ресурсы и уменьшать время первоначального
рендера.translate)
сохраняет плавность анимации даже при динамической подгрузке.Для интерфейсов с большим количеством элементов применяют комбинированный подход:
IntersectionObserver).Пример с IntersectionObserver:
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const target = entry.target;
if (!target.dataset.loaded) {
loadElement(target);
target.dataset.loaded = true;
}
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.lazy-draggable').forEach(el => observer.observe(el));
function loadElement(container) {
const item = document.createElement('div');
item.className = 'draggable-item';
item.textContent = 'Подгруженный элемент';
container.appendChild(item);
}
Этот подход обеспечивает минимальное количество DOM-узлов в любой момент времени, что особенно важно для мобильных устройств и слабых браузеров.
transform вместо top/left обеспечивает
GPU-ускорение и снижает лаги при динамическом добавлении элементов.IntersectionObserver одновременно с
drag-сессией, чтобы не блокировать основной поток.dragstart)dragmove + fetch или
IntersectionObserver)datasettransformИспользование этих подходов позволяет реализовать эффективные, быстрые интерфейсы с большим количеством интерактивных элементов, сохраняя плавность перетаскивания и снижая нагрузку на DOM.