Popper.js предоставляет мощный механизм для управления позиционированием всплывающих элементов относительно их таргетов. По умолчанию библиотека автоматически отслеживает изменения положения таргета и размер всплывающего элемента, обновляя позицию при необходимости. Однако в ряде сценариев требуется полное ручное управление обновлениями для оптимизации производительности или реализации нестандартного поведения.
Для отключения автоматических обновлений используется опция
modifiers с модификатором eventListeners, где
scroll и resize устанавливаются в
false:
import { createPopper } from '@popperjs/core';
const reference = document.querySelector('#button');
const popper = document.querySelector('#tooltip');
const popperInstance = createPopper(reference, popper, {
modifiers: [
{
name: 'eventListeners',
options: {
scroll: false,
resize: false,
},
},
],
});
В этом примере Popper не будет автоматически реагировать на изменения размеров или прокрутки страницы. Всё управление позицией теперь лежит на разработчике.
Popper.js предоставляет метод update() для
принудительного пересчёта позиции:
popperInstance.update();
Метод возвращает промис, который разрешается после завершения всех вычислений и применений стилей. Это позволяет синхронизировать позицию с другими асинхронными действиями, например, с анимацией открытия всплывающего элемента:
popperInstance.update().then(() => {
console.log('Позиция обновлена');
});
forceUpdate()Если необходимо немедленно пересчитать позицию без
асинхронной задержки, применяется метод
forceUpdate():
popperInstance.forceUpdate();
Отличие от update() заключается в том, что
forceUpdate() выполняет синхронное
обновление, игнорируя оптимизации библиотеки и любые очереди
изменений.
Модификаторы Popper.js позволяют управлять поведением позиционирования в реальном времени. При ручном обновлении особенно полезно включение или отключение определённых модификаторов динамически:
popperInstance.setOptions({
modifiers: [
{
name: 'offset',
options: { offset: [0, 20] },
},
{
name: 'preventOverflow',
options: { padding: 8 },
},
],
});
popperInstance.update();
Таким образом, можно изменять смещение, границы и другие параметры без пересоздания Popper-экземпляра.
В случаях, когда элементы часто перемещаются или изменяются размеры контейнеров, рекомендуется:
scroll, resize).update() только по
необходимости, например, при завершении анимации или при
конкретном событии DOM.Пример объединения событий:
let updateScheduled = false;
function scheduleUpdate() {
if (!updateScheduled) {
updateScheduled = true;
requestAnimationFrame(() => {
popperInstance.update();
updateScheduled = false;
});
}
}
document.addEventListener('scroll', scheduleUpdate);
document.addEventListener('resize', scheduleUpdate);
Такой подход снижает нагрузку при высокочастотных событиях.
Ручное управление обновлениями идеально сочетается с библиотеками
анимаций или кастомными скролл-плагинами. После изменения позиции
таргета или размеров всплывающего элемента необходимо явно вызвать
update():
gsap.to(reference, { x: 100, duration: 0.5, onUpdate: () => popperInstance.update() });
Это гарантирует, что Popper синхронизирован с внешними трансформациями.
Ручное управление обновлениями Popper.js позволяет добиться высокой производительности и полной гибкости позиционирования всплывающих элементов, одновременно сохраняя контроль над всеми параметрами и модификаторами библиотеки.