Библиотека Muuri предоставляет гибкий способ организации сеток с динамическими элементами, поддерживая не только статическую загрузку, но и подгрузку контента по требованию. Это особенно важно для страниц с большим количеством элементов, где полная загрузка сразу может негативно сказаться на производительности и UX.
Для начала создаётся базовая сетка Muuri:
const grid = new Muuri('.grid', {
dragEnabled: true,
layout: {
fillGaps: true
}
});
.grid — контейнер, внутри которого
находятся элементы сетки.dragEnabled — включает возможность
перетаскивания элементов.fillGaps — заставляет сетку
автоматически заполнять пустые места после удаления или добавления
элементов.Подгрузка элементов по требованию обычно реализуется через
AJAX или современные методы fetch API.
Сначала создаются новые элементы в DOM, а затем они добавляются в Muuri
с помощью метода add().
async function loadItems(url) {
const response = await fetch(url);
const data = await response.json();
const newItems = data.map(itemData => {
const element = document.createElement('div');
element.classList.add('item');
element.innerHTML = `
<div class="item-content">
<img src="${itemData.image}" alt="${itemData.title}">
<h3>${itemData.title}</h3>
</div>
`;
return element;
});
// Добавление элементов в DOM
const gridContainer = document.querySelector('.grid');
newItems.forEach(el => gridContainer.appendChild(el));
// Добавление элементов в Muuri
grid.add(newItems);
}
add(elements) принимает массив
DOM-элементов и интегрирует их в сетку с анимацией.Для больших сеток часто используется ленивая
загрузка (infinite scroll). Прокрутка отслеживается через
событие scroll или IntersectionObserver.
const observer = new IntersectionObserver(async (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
await loadItems('/api/more-items');
}
}
}, {
root: null,
rootMargin: '0px',
threshold: 1.0
});
observer.observe(document.querySelector('.load-trigger'));
.load-trigger размещается внизу сетки.IntersectionObserver работает эффективнее, чем
постоянная проверка scroll-позиции, так как минимизирует нагрузку на
основной поток.После подгрузки новых элементов может потребоваться обновить сортировку или фильтры сетки:
grid.sort((a, b) => {
return a.getElement().dataset.order - b.getElement().dataset.order;
});
sort() принимает функцию
сравнения и автоматически перестраивает сетку с анимацией.filter(), позволяющий скрывать или
показывать элементы по заданным критериям.grid.filter(item => item.getElement().dataset.category === 'featured');
При динамической загрузке большого количества элементов важно учитывать:
DocumentFragment перед добавлением в контейнер уменьшает
количество перерисовок:const fragment = document.createDocumentFragment();
newItems.forEach(el => fragment.appendChild(el));
gridContainer.appendChild(fragment);
grid.add(newItems);
loading="lazy" для <img> ускоряет
рендеринг сетки.<img src="image.jpg" alt="..." loading="lazy">
Для надёжной работы системы важно предусмотреть обработку ошибок при запросе данных:
async function loadItems(url) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Ошибка загрузки данных');
const data = await response.json();
// создание и добавление элементов
} catch (error) {
console.error(error);
}
}
Такой подход предотвращает поломку сетки при сетевых сбоях или некорректных данных.
Muuri автоматически анимирует новые элементы при добавлении. Для
более сложных эффектов можно использовать опцию
show при добавлении:
grid.show(newItems, {
layout: 'instant',
instant: false
});
В результате подгрузка элементов по требованию в Muuri строится по следующему принципу:
add().Этот подход обеспечивает гибкую, высокопроизводительную сетку с плавной подгрузкой элементов и полной совместимостью с возможностями Muuri по сортировке, фильтрации и анимации.