Жизненный цикл элемента

Жизненный цикл элемента в Muuri начинается с момента его появления в DOM-структуре и регистрации внутри экземпляра сетки. Внутренне каждый элемент представлен объектом Item, который управляет позиционированием, состояниями, анимацией и взаимодействием с другими элементами.

При создании сетки Muuri сканирует контейнер и превращает найденные элементы в управляемые объекты.

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

Контейнер .grid становится управляющей областью, а все дочерние элементы автоматически превращаются в элементы Muuri.

<div class="grid">
  <div class="item">
    <div class="item-content">1</div>
  </div>
  <div class="item">
    <div class="item-content">2</div>
  </div>
</div>

После инициализации происходит несколько внутренних этапов:

  1. Сканирование DOM
  2. Создание объектов Item
  3. Расчет размеров
  4. Размещение в сетке
  5. Первичная анимация

Каждый Item хранит:

  • ссылку на DOM-элемент
  • текущее положение
  • состояние видимости
  • состояние перетаскивания
  • параметры анимации

Получение всех элементов:

const items = grid.getItems();

Получение конкретного элемента по DOM-узлу:

const item = grid.getItem(document.querySelector('.item'));

Объект Item становится центральной сущностью жизненного цикла.


Состояния элемента

Элемент Muuri проходит несколько ключевых состояний:

Состояние Описание
created элемент создан и зарегистрирован
active элемент участвует в раскладке
hidden элемент скрыт
showing выполняется анимация появления
hiding выполняется анимация скрытия
positioning элемент перемещается
dragging элемент перетаскивается

Muuri управляет переходами между этими состояниями автоматически.

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

item.isVisible();
item.isShowing();
item.isHiding();
item.isDragging();

Это позволяет контролировать логику интерфейса и синхронизировать действия.


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

Добавление — один из ключевых этапов жизненного цикла.

grid.add(element);

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

grid.add([element1, element2]);

Пример динамического создания:

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

element.innerHTML = `
  <div class="item-content">New</div>
`;

grid.add(element);

После добавления Muuri выполняет:

  1. создание Item
  2. вычисление размеров
  3. интеграцию в текущий layout
  4. анимацию появления

Если включена анимация layout, элемент плавно перемещается на своё место.


Появление элемента (show)

Элемент может существовать в сетке, но быть скрытым. Переход в видимое состояние выполняется методом show.

grid.show(item);

Или для нескольких элементов:

grid.show([item1, item2]);

Процесс включает:

  1. изменение состояния hidden → showing
  2. запуск CSS-анимации
  3. пересчет layout
  4. переход в состояние active

Muuri автоматически применяет классы:

.muuri-item-shown
.muuri-item-visible

Это позволяет управлять стилями через CSS.


Скрытие элемента (hide)

Скрытие элемента не удаляет его из сетки. Он просто исключается из layout.

grid.hide(item);

Массовое скрытие:

grid.hide(grid.getItems());

Процесс:

  1. состояние visible → hiding
  2. проигрывание анимации
  3. исключение из layout
  4. состояние hidden

После завершения элемент остаётся в DOM, но не влияет на расположение других элементов.

CSS-классы:

.muuri-item-hidden

Перемещение элемента

Muuri автоматически управляет позиционированием через layout-алгоритм.

Принудительный пересчет layout:

grid.layout();

Каждый элемент получает новые координаты:

transform: translate(x, y)

Внутренний процесс перемещения:

  1. вычисление новой позиции
  2. запуск анимации
  3. обновление состояния positioning
  4. фиксация новой позиции

Анимация выполняется через GPU-ускоренные трансформации.


Перетаскивание (drag lifecycle)

Если включено перетаскивание:

const grid = new Muuri('.grid', {
  dragEnabled: true
});

Элемент проходит дополнительные состояния.

Начало перетаскивания

Срабатывает событие:

grid.on('dragStart', function(item) {
  console.log('Drag started');
});

В этот момент:

  • элемент извлекается из layout
  • создаётся placeholder
  • включается режим drag

Перемещение

Во время движения:

grid.on('dragMove', function(item) {
  console.log('Moving');
});

Muuri постоянно:

  1. отслеживает координаты
  2. проверяет коллизии
  3. обновляет потенциальную позицию

Завершение перетаскивания

grid.on('dragEnd', function(item) {
  console.log('Drag finished');
});

Процесс завершения:

  1. вычисляется новая позиция
  2. обновляется порядок элементов
  3. пересчитывается layout
  4. элемент возвращается в поток сетки

Сортировка элементов

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

Сортировка:

grid.sort(function(a, b) {
  return a.getElement().dataset.order - b.getElement().dataset.order;
});

После сортировки:

  1. меняется внутренний порядок Item
  2. выполняется layout
  3. запускается анимация перемещения

Фильтрация элементов

Фильтрация временно скрывает элементы.

grid.filter(function(item) {
  return item.getElement().dataset.category === 'news';
});

Muuri:

  1. проверяет каждый элемент
  2. применяет show или hide
  3. выполняет layout

Таким образом элементы проходят те же стадии жизненного цикла.


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

Удаление — финальная стадия жизненного цикла.

grid.remove(item);

Удаление нескольких элементов:

grid.remove([item1, item2]);

Внутренний процесс:

  1. удаление из массива элементов
  2. удаление DOM-узла
  3. пересчет layout

Можно отключить удаление DOM-элемента:

grid.remove(item, { removeElements: false });

Обновление размеров элемента

Если содержимое элемента изменилось, необходимо обновить размеры.

grid.refreshItems().layout();

Либо для конкретного элемента:

item.refreshDimensions();
grid.layout();

Этапы:

  1. пересчет размеров
  2. обновление внутренних данных
  3. пересчет layout

Без обновления размеры будут некорректными.


Обработка событий жизненного цикла

Muuri предоставляет большое количество событий.

layoutStart

grid.on('layoutStart', function(items) {
  console.log('Layout start');
});

Срабатывает перед перерасчетом сетки.


layoutEnd

grid.on('layoutEnd', function(items) {
  console.log('Layout finished');
});

Фиксация новой структуры сетки.


showStart / showEnd

grid.on('showStart', function(items) {});
grid.on('showEnd', function(items) {});

hideStart / hideEnd

grid.on('hideStart', function(items) {});
grid.on('hideEnd', function(items) {});

dragStart / dragMove / dragEnd

Позволяют полностью контролировать поведение перетаскивания.


Внутренняя структура элемента

Каждый Item содержит несколько внутренних компонентов:

Item
 ├── element
 ├── layout
 ├── drag
 ├── visibility
 ├── animation

element

DOM-узел.

layout

Координаты и размеры.

drag

Состояние перетаскивания.

visibility

Состояние отображения.

animation

Данные текущей анимации.


Финальная стадия жизненного цикла

Элемент перестаёт существовать для Muuri, когда:

  1. удалён из сетки через remove
  2. уничтожена сама сетка

Уничтожение сетки:

grid.destroy();

После этого:

  • все события отключаются
  • элементы возвращаются к обычному DOM-поведению
  • внутренние структуры очищаются

Объекты Item освобождаются сборщиком мусора JavaScript, завершая жизненный цикл элемента внутри Muuri.