Проверка modifiers

В Popper.js modifiers играют ключевую роль в управлении поведением всплывающих элементов (попперов). Они позволяют гибко настраивать позиционирование, смещения, динамическое реагирование на изменения размеров и предотвращение выхода поппера за границы контейнера. Понимание проверки и валидации modifiers критично для правильной работы библиотеки.


Структура modifiers

Каждый модификатор представляет собой объект со следующими ключевыми свойствами:

  • name — уникальный идентификатор модификатора.

  • enabled — логическое значение, включен модификатор или нет.

  • phase — стадия жизненного цикла Popper.js, на которой модификатор выполняется. Возможные значения:

    • beforeRead
    • read
    • afterRead
    • beforeMain
    • main
    • afterMain
    • beforeWrite
    • write
    • afterWrite
  • fn — функция, реализующая логику модификатора. Она получает объект state, name, options и должна возвращать изменения к state.

  • options — объект настроек модификатора, специфичных для каждой реализации.

  • requires — массив имён модификаторов, от которых зависит данный модификатор.

  • requiresIfExists — массив модификаторов, которые должны быть учтены, если они присутствуют.

Пример базового модификатора:

const exampleModifier = {
  name: 'example',
  enabled: true,
  phase: 'main',
  fn({ state, options }) {
    state.styles.popper.left += options.offset || 0;
  },
  options: {
    offset: 10
  }
};

Валидация модификаторов

Popper.js выполняет внутреннюю проверку модификаторов для предотвращения ошибок при инициализации поппера. Основные проверки включают:

  1. Проверка уникальности name Дублирующие имена модификаторов приводят к конфликтам. При обнаружении одинаковых имён Popper.js игнорирует второй модификатор и выводит предупреждение в консоль.

  2. Проверка enabled Модификаторы с enabled: false не выполняются, но сохраняются в состоянии для возможного динамического включения.

  3. Проверка phase Некорректные значения phase вызывают игнорирование модификатора. Популярные ошибки включают опечатки (mainn вместо main) или отсутствие phase.

  4. Проверка fn Функция модификатора должна быть callable. Если fn не является функцией, модификатор пропускается, а библиотека выводит предупреждение.

  5. Проверка зависимостей (requires и requiresIfExists) Если модификатор зависит от другого, который отсутствует или отключён, Popper.js предупреждает об этом. requiresIfExists более гибок — отсутствие модификатора не вызывает ошибки.


Примеры ошибок и их диагностика

Дублирование имён:

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

Консоль выведет предупреждение о конфликте имён. Решение — использовать уникальные имена для всех кастомных модификаторов.

Некорректный phase:

{
  name: 'customPhase',
  enabled: true,
  phase: 'mid', // неверное значение
  fn: ({ state }) => { state.styles.popper.top += 10; }
}

Popper.js пропустит выполнение данного модификатора.

Отсутствие fn:

{
  name: 'noFunction',
  enabled: true,
  phase: 'main'
}

Без функции модификатор не будет работать. Необходимо добавить fn с корректной реализацией.


Динамическая проверка модификаторов

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

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

// Отключение модификатора в runtime
popperInstance.setOptions({
  modifiers: [{ name: 'flip', enabled: false }]
});

Валидация выполняется при каждом обновлении опций, что гарантирует корректное применение изменений без нарушений логики.


Встроенные инструменты диагностики

Popper.js выводит предупреждения через console.warn при:

  • Дублирующихся или неизвестных модификаторах.
  • Некорректных зависимостях.
  • Неправильных типах свойств (fn не функция, phase некорректен).

Для сложных приложений рекомендуется использовать эти сообщения как основу для unit-тестов модификаторов.


Рекомендации по проверке

  1. Всегда задавать уникальные name.
  2. Проверять корректность phase согласно документации.
  3. Использовать requires и requiresIfExists для управления зависимостями.
  4. Убедиться, что все кастомные fn корректно модифицируют state.
  5. Периодически обновлять Popper.js до последних версий для актуальных проверок модификаторов.

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