Структура DOM-элементов

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

Минимальная структура включает два уровня:

  1. контейнер сетки
  2. элементы сетки

Простейшая разметка:

<div class="grid">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>

После инициализации сетки:

const grid = new Muuri('.grid');

контейнер .grid становится управляющим элементом, а каждый .item преобразуется во внутренний объект Muuri — Grid Item.

Muuri не создаёт элементы автоматически. Библиотека использует существующие DOM-узлы и добавляет к ним служебные свойства и стили.


Роль контейнера сетки

Контейнер — это DOM-элемент, внутри которого располагаются элементы сетки. Он выполняет несколько функций:

  • хранит список элементов
  • управляет алгоритмом раскладки
  • определяет границы перемещения
  • выступает точкой инициализации Muuri

Пример контейнера:

<div class="grid"></div>

Рекомендуемые CSS-правила:

.grid {
  position: relative;
}

Контейнер должен иметь позиционирование, поскольку Muuri размещает элементы с помощью position: absolute.


Структура элемента сетки

Каждый элемент сетки представляет собой отдельный DOM-узел.

Пример:

<div class="item"></div>

После инициализации Muuri:

  • элемент остаётся в DOM
  • ему назначается position: absolute
  • координаты рассчитываются алгоритмом layout

Пример структуры после инициализации:

<div class="grid">
  <div class="item muuri-item"></div>
  <div class="item muuri-item"></div>
  <div class="item muuri-item"></div>
</div>

Muuri добавляет служебные классы:

  • muuri-item
  • muuri-item-hidden
  • muuri-item-releasing
  • muuri-item-dragging

Эти классы используются для управления состоянием элементов.


Внутренний контейнер элемента

На практике элемент сетки обычно содержит внутренний контейнер. Это необходимо для анимаций, трансформаций и удобной работы со стилями.

Типичная структура:

<div class="grid">
  <div class="item">
    <div class="item-content">
      Контент
    </div>
  </div>
</div>

Причины использования вложенного контейнера:

  • Muuri применяет трансформации к родительскому .item
  • содержимое можно анимировать отдельно
  • упрощается работа со стилями

CSS-пример:

.item {
  width: 200px;
  height: 150px;
}

.item-content {
  width: 100%;
  height: 100%;
}

Полная рекомендуемая структура

Практически во всех проектах используется следующая схема:

<div class="grid">

  <div class="item">
    <div class="item-content">
      <h3>Карточка 1</h3>
      <p>Описание</p>
    </div>
  </div>

  <div class="item">
    <div class="item-content">
      <h3>Карточка 2</h3>
      <p>Описание</p>
    </div>
  </div>

  <div class="item">
    <div class="item-content">
      <h3>Карточка 3</h3>
      <p>Описание</p>
    </div>
  </div>

</div>

Инициализация:

const grid = new Muuri('.grid', {
  items: '.item'
});

Параметр items позволяет указать селектор элементов внутри контейнера.


Как Muuri взаимодействует с DOM

При создании сетки Muuri выполняет следующие действия:

  1. считывает контейнер
  2. находит элементы
  3. создаёт объект GridItem для каждого элемента
  4. рассчитывает размеры
  5. применяет абсолютное позиционирование
  6. выполняет раскладку

Внутренняя модель:

Muuri Grid
   │
   ├── Item
   │     └── DOM element
   │
   ├── Item
   │     └── DOM element
   │
   └── Item
         └── DOM element

Каждый Item содержит ссылку на соответствующий DOM-узел.


Служебные элементы Muuri

В процессе работы Muuri может добавлять дополнительные временные элементы.

Основные служебные структуры:

Placeholder

Появляется во время drag-and-drop и показывает будущее место элемента.

Drag container

Иногда используется отдельный контейнер для перетаскиваемого элемента.

Пример конфигурации:

const grid = new Muuri('.grid', {
  dragContainer: document.body
});

В этом случае перетаскиваемый элемент временно переносится в body.


Атрибуты и классы элементов

Muuri активно использует CSS-классы для отражения состояния элементов.

Основные классы:

Класс Назначение
muuri-item базовый класс элемента
muuri-item-shown элемент отображается
muuri-item-hidden элемент скрыт
muuri-item-positioning выполняется анимация позиции
muuri-item-dragging элемент перетаскивается
muuri-item-releasing элемент возвращается после drag

Пример DOM в момент перетаскивания:

<div class="item muuri-item muuri-item-dragging">
  <div class="item-content"></div>
</div>

Связь DOM и объектов Muuri

Каждый DOM-элемент оборачивается во внутренний объект Muuri.

Получение объекта элемента:

const item = grid.getItems()[0];

Получение DOM-элемента:

const element = item.getElement();

Обратная операция — получение объекта Muuri по DOM-узлу:

const item = grid.getItem(element);

Это позволяет работать одновременно с DOM и внутренней моделью библиотеки.


Динамическое добавление элементов

DOM-структура может изменяться после инициализации.

Добавление нового элемента:

const element = document.createElement('div');
element.classList.add('item');

grid.add(element);

После добавления:

  1. элемент вставляется в контейнер
  2. создаётся объект Item
  3. выполняется перерасчёт layout

Удаление элементов

Удаление элемента возможно через DOM или API Muuri.

Через API:

const item = grid.getItems()[0];
grid.remove(item);

После удаления:

  • DOM-узел удаляется
  • объект Item уничтожается
  • сетка пересчитывается

Влияние структуры DOM на производительность

Неправильная структура может ухудшить производительность.

Основные рекомендации:

1. Минимизировать глубину DOM

Каждый дополнительный уровень усложняет рендеринг.

2. Использовать фиксированные размеры

Muuri быстрее рассчитывает layout, если известны размеры элементов.

.item {
  width: 200px;
  height: 150px;
}

3. Избегать сложных вложенных layout

Flexbox или Grid внутри .item могут увеличивать время перерасчёта.


Работа с нестандартными структурами

Muuri допускает гибкость в структуре элементов.

Пример карточки:

<div class="item">
  <article class="card">

    <header class="card-header">
      Заголовок
    </header>

    <div class="card-body">
      Контент
    </div>

    <footer class="card-footer">
      Кнопки
    </footer>

  </article>
</div>

Главное требование — корневой элемент карточки должен быть .item, поскольку именно он участвует в алгоритме размещения.


Вложенные сетки

Muuri поддерживает вложенные структуры.

Пример:

<div class="grid">

  <div class="item">
    <div class="item-content">
      <div class="inner-grid">
        <div class="inner-item"></div>
        <div class="inner-item"></div>
      </div>
    </div>
  </div>

</div>

Каждая вложенная сетка инициализируется отдельно:

const outerGrid = new Muuri('.grid');
const innerGrid = new Muuri('.inner-grid');

Типичный DOM после полной инициализации

Пример реального DOM-дерева:

<div class="grid">

  <div class="item muuri-item muuri-item-shown"
       style="position: absolute; transform: translate(0px, 0px);">

    <div class="item-content">
      Карточка
    </div>

  </div>

  <div class="item muuri-item muuri-item-shown"
       style="position: absolute; transform: translate(210px, 0px);">

    <div class="item-content">
      Карточка
    </div>

  </div>

</div>

Muuri управляет расположением через:

  • position: absolute
  • transform: translate(...)

Такой подход обеспечивает:

  • аппаратное ускорение
  • плавные анимации
  • высокую производительность при большом количестве элементов.

Основные правила построения DOM

Ключевые принципы структуры:

  1. контейнер сетки должен быть одним родителем всех элементов
  2. каждый элемент сетки должен иметь общий селектор
  3. элементы должны быть прямыми потомками контейнера
  4. размеры элементов должны быть определены CSS
  5. рекомендуется использовать внутренний контейнер контента

Эти правила позволяют Muuri корректно рассчитывать layout, выполнять анимации и обеспечивать стабильную работу интерактивной сетки.