Жизненный цикл экземпляра Popper

Экземпляр Popper создаётся с помощью конструктора Popper.createPopper(reference, popper, options). Здесь:

  • reference – элемент, относительно которого будет позиционироваться всплывающий блок. Может быть DOM-элементом, объектом с координатами или виртуальным элементом с функцией getBoundingClientRect.
  • popper – всплывающий элемент, который необходимо позиционировать.
  • options – объект с настройками позиционирования и поведения Popper. Включает placement, modifiers, strategy.

Пример базового создания Popper:

const reference = document.querySelector('#button');
const popper = document.querySelector('#tooltip');

const popperInstance = Popper.createPopper(reference, popper, {
  placement: 'top',
  modifiers: [
    { name: 'offset', options: { offset: [0, 8] } }
  ],
});

Параметры жизненного цикла

Жизненный цикл Popper включает несколько ключевых этапов:

  1. Инициализация При создании экземпляра происходит:

    • Сбор информации о положении и размере reference и popper.
    • Применение указанных модификаторов.
    • Первичная установка позиции элемента.
  2. Обновление (update) Метод popperInstance.update() пересчитывает позицию и применяет новые стили к элементу. Может быть вызван вручную или автоматически при изменении размеров окна или содержимого.

  3. Асинхронное обновление (forceUpdate) Метод popperInstance.forceUpdate() выполняет немедленное перерасчитывание позиции без ожидания очереди обновлений. Используется в случаях, когда необходимо синхронное обновление.

  4. Деструктуризация (destroy) Метод popperInstance.destroy() полностью удаляет Popper:

    • Отменяет все слушатели событий.
    • Очищает модификаторы и применённые стили.
    • Делает объект экземпляра неработоспособным.

Модификаторы и их роль в жизненном цикле

Модификаторы — это плагины, влияющие на поведение Popper. Они работают в определённом порядке и могут изменять как вычисления, так и стили:

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

Модификаторы имеют следующие жизненные этапы внутри Popper:

  1. BeforeRead / Read — сбор исходных данных о DOM, размерах и позициях.
  2. BeforeMain / Main — вычисление окончательной позиции и модификации координат.
  3. AfterMain / BeforeWrite / Write — применение стилей к элементу и стрелке.
  4. AfterWrite — финальные корректировки и колбэки модификаторов.

Автоматические обновления

По умолчанию Popper отслеживает:

  • Изменения размеров окна (resize).
  • Скролл контейнеров (scroll).

Для контроля частоты обновлений используется eventListeners модификатор. Он активируется автоматически, если не указан вручную:

modifiers: [
  { name: 'eventListeners', enabled: true }
]

Можно отключить автоматическое слежение для оптимизации производительности, особенно при большом количестве Popper-элементов.

Виртуальные элементы

Popper позволяет работать с элементами, которые не находятся в DOM напрямую, через объект с методом getBoundingClientRect:

const virtualReference = {
  getBoundingClientRect: () => ({
    width: 100,
    height: 40,
    top: 200,
    left: 300,
    right: 400,
    bottom: 240,
  }),
  contextElement: document.body
};

const popperInstance = Popper.createPopper(virtualReference, popper);

Это полезно для всплывающих подсказок, связанных с координатами мыши или динамически созданными областями.

Стратегии позиционирования

Popper поддерживает две стратегии:

  • absolute — элемент позиционируется относительно ближайшего родителя с position: relative или absolute.
  • fixed — элемент позиционируется относительно окна, игнорируя прокрутку.

Стратегия задаётся через опцию strategy:

const popperInstance = Popper.createPopper(reference, popper, {
  strategy: 'fixed'
});

Программное управление

Жизненный цикл можно контролировать через методы экземпляра:

  • update() — асинхронное обновление позиции.
  • forceUpdate() — немедленное пересчитывание.
  • setOptions(options) — обновление конфигурации и модификаторов.
  • destroy() — завершение работы Popper.

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

popperInstance.setOptions({
  placement: 'bottom',
  modifiers: [{ name: 'offset', options: { offset: [0, 16] } }]
});
popperInstance.update();

Особенности производительности

  • Попперы создаются относительно DOM-элементов, поэтому частые изменения размеров могут вызывать перерисовку.
  • Модификаторы eventListeners и flip потребляют ресурсы при большом количестве элементов.
  • Использование virtual element и ручного управления update() позволяет снизить нагрузку.

Жизненный цикл Popper организован так, чтобы обеспечить плавное позиционирование, гибкость модификаций и эффективное управление ресурсами при работе с динамическими интерфейсами.