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

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


update и forceUpdate

Каждый экземпляр поппера имеет методы update и forceUpdate:

  • update() — асинхронно пересчитывает позицию поппера с учётом текущего положения reference-элемента и видимой области. Возвращает промис, который резолвится объектом с актуальными координатами.
  • forceUpdate() — синхронно выполняет пересчёт и сразу применяет новые стили к попперу, игнорируя оптимизации. Используется в случаях, когда нужно гарантированно обновить позицию до следующего рендеринга браузера.

Пример использования:

import { createPopper } from '@popperjs/core';

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

const popperInstance = createPopper(button, tooltip, {
  placement: 'top'
});

// Асинхронное обновление
popperInstance.update().then(({ x, y }) => {
  console.log(`Новая позиция: ${x}, ${y}`);
});

// Синхронное обновление
popperInstance.forceUpdate();

autoUpdate — автоматическое слежение за изменениями

Popper.js предоставляет функцию autoUpdate, которая автоматически вызывает пересчёт позиции при изменениях DOM, скролле или изменении размеров окна. Она особенно полезна для интерактивных элементов и всплывающих подсказок.

import { autoUpdate, createPopper } from '@popperjs/core';

const cleanup = autoUpdate(reference, popper, () => {
  popperInstance.update();
});

// Для прекращения автоматического слежения
cleanup();

Ключевые моменты:

  • autoUpdate возвращает функцию cleanup, которая отключает отслеживание.

  • Слежение включает:

    • Изменение размеров reference-элемента
    • Изменение размеров поппера
    • Скролл и изменение видимой области
  • Можно комбинировать с MutationObserver для отслеживания динамического добавления или удаления элементов.


Опции автоматического обновления

Popper.js позволяет тонко настраивать поведение автоматического обновления через параметры функции autoUpdate:

autoUpdate(reference, popper, updateCallback, {
  ancestorScroll: true, // слежение за прокруткой родительских контейнеров
  ancestorResize: true, // слежение за изменением размеров родителей
  elementResize: true, // слежение за изменением размеров поппера
  mutationObserver: true // слежение за изменением DOM
});
  • ancestorScroll — включает слежение за скроллом всех предков reference-элемента.
  • ancestorResize — отслеживает изменение размеров всех предков.
  • elementResize — реагирует на изменение размеров самого поппера.
  • mutationObserver — отслеживает добавление, удаление или изменение элементов внутри reference и popper.

Эти опции позволяют минимизировать ненужные пересчёты и оптимизировать производительность.


Производительность и оптимизация

Автоматическое обновление может быть ресурсозатратным при большом количестве элементов. Для оптимизации рекомендуется:

  1. Использовать дебаунсинг или троттлинг внутри callback функции:
import { debounce } from 'lodash';

autoUpdate(reference, popper, debounce(() => {
  popperInstance.update();
}, 50));
  1. Ограничивать слежение только необходимыми событиями (ancestorScroll, elementResize), отключая ненужные опции.
  2. Вызывать cleanup() при удалении поппера из DOM, чтобы избежать утечек памяти.

Автоматическое обновление с модификаторами

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

Пример модификатора, реагирующего на изменения:

const popperInstance = createPopper(reference, popper, {
  placement: 'right',
  modifiers: [
    {
      name: 'offset',
      options: {
        offset: [0, 10]
      }
    },
    {
      name: 'flip',
      options: {
        fallbackPlacements: ['top', 'bottom']
      }
    }
  ]
});

При любом изменении размера или позиции autoUpdate пересчитает положение и применит модификаторы заново, обеспечивая корректное отображение.


Практические сценарии использования

  • Всплывающие подсказки: их размеры могут меняться в зависимости от контента.
  • Контекстные меню: меню должно оставаться привязанным к элементу при прокрутке или изменении размеров окна.
  • Динамические панели: панели, создаваемые и удаляемые по событию, должны сохранять правильную позицию без ручного пересчёта.

Автоматическое обновление в Popper.js обеспечивает надежное, динамическое позиционирование, освобождая разработчиков от необходимости вручную управлять пересчётом координат при изменении интерфейса.