Popper.js управляет позиционированием всплывающих элементов относительно опорных элементов на странице. В основе этого механизма лежит state, объект, содержащий актуальную информацию о позиционировании, размере и состоянии каждого элемента, участвующего в расчётах. Ключевое место в state занимают elements, которые представляют собой ссылки на реальные DOM-узлы.
elementsВ state объект elements представлен как
объект с двумя основными свойствами:
state.elements = {
reference: HTMLElement,
popper: HTMLElement,
arrow?: HTMLElement
};
null.Каждое из этих свойств является живой ссылкой на DOM, что позволяет Popper.js напрямую манипулировать их размерами и положением при каждом обновлении state.
Элементы в state могут динамически изменяться. Popper.js предоставляет методы, позволяющие заменять reference или popper без пересоздания всей инстанции:
popperInstance.setOptions({
modifiers: [
{
name: 'updateElements',
enabled: true,
phase: 'beforeWrite',
fn({ state }) {
state.elements.reference = document.querySelector('#newReference');
}
}
]
});
Важные моменты:
Модификаторы Popper.js получают объект state на каждом цикле обновления. Для работы с элементами важно помнить:
modifiers: [
{
name: 'exampleModifier',
enabled: true,
phase: 'main',
fn({ state }) {
const refRect = state.elements.reference.getBoundingClientRect();
const popperRect = state.elements.popper.getBoundingClientRect();
console.log('Reference ширина:', refRect.width);
console.log('Popper высота:', popperRect.height);
}
}
]
getBoundingClientRect() возвращает актуальные размеры и
положение элементов на странице.state.elements всегда содержит актуальные DOM-узлы,
даже если они были заменены динамически.if (state.elements.arrow) {
const arrowRect = state.elements.arrow.getBoundingClientRect();
}
Попперы часто появляются после асинхронных операций, например, при загрузке данных. Чтобы избежать ошибок:
if (state.elements.reference && state.elements.popper) {
popperInstance.update();
}
null.popperInstance.update().Popper.js позволяет подставлять элементы через функции возвращающие DOM:
const popperInstance = Popper.createPopper(() => document.querySelector('#dynamicRef'), () => document.querySelector('#dynamicPopper'));
state.elementsstate.elements.reference = document.getElementById('newButton');
popperInstance.update();
state.elements.popper = document.getElementById('newTooltip');
popperInstance.update();
if (state.elements.arrow) {
const arrowWidth = state.elements.arrow.offsetWidth;
const popperWidth = state.elements.popper.offsetWidth;
state.modifiersData.arrow = { offset: (popperWidth - arrowWidth) / 2 };
}
Эти операции позволяют управлять позиционированием без пересоздания всей инстанции, повышая производительность и гибкость интерфейса.
elements в stateЭта модель обеспечивает точное, гибкое и высокопроизводительное управление всплывающими элементами, делая Popper.js универсальным инструментом для современных интерфейсов.