Обработка DOM при изменениях

Библиотека Muuri предоставляет мощный механизм для управления сеткой элементов с поддержкой анимаций, фильтрации, сортировки и перетаскивания. Центральным аспектом её работы является способность реагировать на изменения DOM и корректно обновлять сетку, сохраняя целостность анимаций и позиции элементов.


Слежение за изменениями 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 будет использовать старые размеры, что может нарушить визуальный порядок.


Работа с MutationObserver

Для автоматического реагирования на изменения 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 обновляет размеры элементов и выполняет перераспределение.


Выводы по обработке DOM

  • Любое изменение DOM требует уведомления сетки через add(), remove(), refreshItems() и layout().
  • Автоматическое отслеживание изменений DOM возможно с MutationObserver.
  • Группировка обновлений через requestAnimationFrame повышает производительность.
  • Асинхронный контент требует повторного расчёта размеров для сохранения правильного расположения элементов.

Эти принципы позволяют Muuri эффективно работать с динамическим контентом, сохраняя анимации и целостность сетки.