При работе с большим количеством элементов производительность и отзывчивость интерфейса становятся критичными. Muuri предоставляет гибкие возможности для управления сеткой, но важно правильно организовать инициализацию.
const grid = new Muuri('.grid', {
layoutDuration: 400,
layoutEasing: 'ease',
dragEnabled: true,
dragSortPredicate: {
threshold: 50,
action: 'move'
}
});
Ключевые моменты при инициализации:
dragStartPredicate.При добавлении или удалении множества элементов важно использовать
методы add и remove в комбинации с
synchronizeLayout.
// Создание массива новых элементов
const newItems = [...document.querySelectorAll('.new-item')].map(el => new Muuri.Item(el));
// Добавление всех элементов в сетку за один вызов
grid.add(newItems, {layout: false});
// Синхронизация и анимация всех элементов
grid.layout(true);
Особенности:
grid.layout(true) рекомендуется отключать
автоматическое обновление через layoutOnResize: false,
чтобы избежать множественных перерасчетов при добавлении большого числа
элементов.remove(items, options) также поддерживает флаг
{removeElements: true}, который позволяет удалять элементы
из DOM без дополнительного обхода.const itemsToRemove = grid.getItems('.old-item');
grid.remove(itemsToRemove, {removeElements: true, layout: false});
grid.layout(true);
Для сеток с сотнями и тысячами элементов эффективнее использовать виртуализацию, когда отображаются только элементы, находящиеся в зоне видимости. Muuri напрямую не предоставляет встроенной виртуализации, но её можно реализовать совместно с IntersectionObserver или scroll-обработчиками.
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
const item = entry.target;
if (entry.isIntersecting) {
grid.show(item, {layout: false});
} else {
grid.hide(item, {layout: false});
}
});
}, {root: document.querySelector('.grid'), threshold: 0.1});
document.querySelectorAll('.grid-item').forEach(item => observer.observe(item));
Выводы по виртуализации:
grid.layout(true), чтобы пересчитать позиции оставшихся
видимых элементов.Muuri поддерживает фильтрацию элементов через функцию
filter, что особенно полезно при работе с сотнями
элементов.
grid.filter(item => item.getElement().classList.contains('active'));
Советы для производительности:
filter с layout: false, а затем вызвать
единоразовый grid.layout(true).При работе с большим количеством элементов события drag могут стать узким местом. В Muuri можно оптимизировать следующие параметры:
'move' и 'swap' может значительно повлиять на
производительность при сотнях элементов.const grid = new Muuri('.grid', {
dragEnabled: true,
dragSortPredicate: {
threshold: 60,
action: 'swap'
},
dragReleaseDuration: 150
});
Muuri предоставляет метод refreshItems() для обновления
данных о размерах и позициях элементов. При большом числе элементов
лучше вызывать refreshItems() после всех изменений, а не по
одному элементу.
grid.refreshItems().layout();
Рекомендации:
item.getElement().style.height = '100px' должно быть
согласовано с grid.refreshItems().layout(true) после
refreshItems() гарантирует корректное перераспределение
всех элементов сетки.При интеграции Muuri с динамическим контентом (например, подгрузка картинок или постов) важно добавлять элементы асинхронно, чтобы не блокировать интерфейс.
fetch('/api/items')
.then(res => res.json())
.then(data => {
const elements = data.map(d => {
const el = document.createElement('div');
el.className = 'grid-item';
el.textContent = d.title;
return el;
});
grid.add(elements, {layout: true});
});
Особенности:
imagesLoaded
перед добавлением в сетку, чтобы избежать неправильного расчета
размеров.Muuri генерирует события, которые полезно использовать для масштабных сеток:
grid.on('layoutEnd', () => console.log('Перестройка сетки завершена'));
grid.on('dragEnd', item => console.log('Элемент перемещён:', item.getElement()));
Совет: При большом количестве элементов обработчики событий не должны выполнять сложные вычисления на каждый элемент — лучше использовать батчинг или делегирование.
layout().Эти подходы обеспечивают стабильную производительность Muuri даже при работе с сотнями и тысячами элементов, сохраняя плавность анимаций и отзывчивость интерфейса.