Фаза main

Фаза main является одной из ключевых в жизненном цикле позиционирования элементов в Popper.js. Она выполняется после фаз read и beforeMain, когда уже доступны все исходные данные о положении элементов, но ещё не применены окончательные корректировки. Основная задача main — вычисление точного расположения поппера и применение модификаторов, влияющих на его позицию.


Порядок выполнения

Фаза main выполняется строго по цепочке модификаторов, у которых указано поле phase: 'main'. Попеременно обрабатываются все модификаторы в том порядке, который указан в массиве modifiers при создании поппера. Важное правило: модификаторы main могут изменять данные о смещении (offsets) и размеры элементов, которые затем используются фазой write для рендеринга.


Основные свойства данных, доступных в фазе main

В функцию модификатора на фазе main передается объект state, который содержит:

  • state.rects – размеры и позиции reference и popper элементов:

    • state.rects.reference – объект с координатами и размерами reference.
    • state.rects.popper – объект с размерами поппера.
  • state.modifiersData – объект, в котором модификаторы могут сохранять промежуточные вычисления.

  • state.placement – текущее предполагаемое расположение поппера (например, "top", "bottom-start").

  • state.options – объект с опциями Popper, включая массив модификаторов и глобальные настройки.

Модификаторы фазы main используют эти данные для расчета точного смещения поппера относительно reference.


Работа с offsets

Самым частым применением модификаторов на фазе main является корректировка смещений по осям X и Y. Для этого Popper.js использует структуру:

state.modifiersData.offset = {
  x: 0,
  y: 0
};

Модификатор может изменить эти значения, и итоговые координаты будут учтены в фазе write. Пример модификатора:

const customOffset = {
  name: 'customOffset',
  phase: 'main',
  fn({ state }) {
    state.modifiersData.offset = {
      x: 10,
      y: 20
    };
  }
};

Использование данных о размере и позиции

В фазе main доступно точное положение reference и popper. Это позволяет:

  • Реализовать динамическое смещение относительно границ контейнера.
  • Изменять placement на основе размеров окна и элемента.
  • Сохранять промежуточные данные для других модификаторов.

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

const dynamicPlacement = {
  name: 'dynamicPlacement',
  phase: 'main',
  fn({ state }) {
    if (state.rects.reference.width > 200) {
      state.placement = 'bottom';
    } else {
      state.placement = 'top';
    }
  }
};

Взаимодействие с другими фазами

Фаза main является промежуточной, поэтому:

  1. Она читает данные, подготовленные в фазах read и beforeMain.
  2. Она модифицирует данные, которые будут использоваться в write.
  3. Любые изменения смещений, размеров или placement фиксируются в state, чтобы последующие модификаторы, например на фазе afterMain, могли учитывать их.

Важно помнить, что нельзя напрямую изменять DOM в фазе main. Все вычисления должны оставаться в состоянии state.


Практические модификаторы фазы main

  • offset — стандартный модификатор, который управляет смещением по осям.
  • flip — решает, нужно ли менять placement, если поппер выходит за границы видимой области.
  • preventOverflow — корректирует смещения, чтобы поппер не выходил за границы контейнера.

Каждый из этих модификаторов в какой-то степени зависит от точных данных state.rects, которые вычисляются до начала фазы main.


Рекомендации по созданию кастомных модификаторов main

  • Использовать только данные state без прямого изменения DOM.
  • Сохранять промежуточные расчеты в state.modifiersData.
  • Изменять state.placement и state.modifiersData.offset для управления окончательным расположением.
  • Учитывать порядок модификаторов: изменения будут учитываться только для последующих модификаторов в списке.

Фаза main в Popper.js является центральной для вычисления точной позиции поппера. Она соединяет чтение данных и подготовку к визуальному отображению, обеспечивая гибкость и контроль над поведением элементов при позиционировании.