Библиотека Muuri предоставляет мощный механизм для управления сеткой элементов с поддержкой анимаций, фильтрации, сортировки и перетаскивания. Центральным аспектом её работы является способность реагировать на изменения DOM и корректно обновлять сетку, сохраняя целостность анимаций и позиции элементов.
Muuri не отслеживает DOM автоматически после инициализации сетки. Любые добавления, удаления или изменения элементов требуют уведомления сетки через специальные методы:
grid.add([items], options) — добавляет новые элементы в
сетку.grid.remove([items], options) — удаляет элементы с
возможностью анимации.grid.refreshItems([items]) — обновляет внутренние
размеры и данные элементов.grid.layout([instant]) — пересчитывает расположение
всех элементов в сетке.Важно понимать, что любое прямое изменение DOM без уведомления Muuri может привести к некорректной визуализации: элементы могут пересекаться или не участвовать в сортировке и фильтрации.
Для добавления элементов необходимо:
const grid = new Muuri('.grid');
const newItem = document.createElement('div');
newItem.className = 'item';
newItem.innerHTML = '<div class="item-content">Новый элемент</div>';
grid.add(newItem, { layout: true });
Ключевой момент — после добавления элемента нужно обновить сетку
через опцию layout: true, чтобы новый элемент корректно
вошёл в анимацию расположения.
Для удаления элемента:
grid.remove(itemElement, { removeElements: true, layout: true });
Опция removeElements: true физически удаляет DOM-элемент
после анимации. Без неё элемент останется в DOM, но будет исключён из
сетки.
Если размеры или содержимое элементов изменились, необходимо вызвать:
grid.refreshItems([itemElement]).layout();
refreshItems() пересчитывает размеры элементов.layout() гарантирует перераспределение сетки с
анимацией.Без вызова refreshItems() Muuri будет использовать
старые размеры, что может нарушить визуальный
порядок.
Для автоматического реагирования на изменения DOM можно использовать
MutationObserver:
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
if (mutation.addedNodes.length) {
grid.add(Array.from(mutation.addedNodes), { layout: true });
}
if (mutation.removedNodes.length) {
grid.remove(Array.from(mutation.removedNodes), { removeElements: false, layout: true });
}
}
}
});
observer.observe(gridElement, { childList: true, subtree: false });
childList: true отслеживает добавление и удаление
непосредственных потомков.subtree: false ограничивает наблюдение только
элементами сетки, исключая вложенные DOM-структуры.Использование MutationObserver позволяет
синхронизировать Muuri с динамическим содержимым,
особенно при интеграции с фреймворками, где DOM изменяется часто.
При большом количестве элементов следует избегать частого вызова
layout() для каждого изменения. Вместо этого рекомендуется
группировать обновления:
requestAnimationFrame(() => {
grid.refreshItems().layout();
});
Это позволяет Muuri обновлять позиции всех элементов за один кадр, минимизируя нагрузку на рендер и сохраняя плавность анимации.
Если элементы содержат изображения или динамический контент, размеры могут изменяться после загрузки. Для корректного позиционирования необходимо:
imagesLoaded(gridElement, () => {
grid.refreshItems().layout();
});
imagesLoaded — сторонняя библиотека или кастомный код,
отслеживающий завершение загрузки изображений. После этого Muuri
обновляет размеры элементов и выполняет перераспределение.
add(), remove(), refreshItems() и
layout().MutationObserver.requestAnimationFrame
повышает производительность.Эти принципы позволяют Muuri эффективно работать с динамическим контентом, сохраняя анимации и целостность сетки.