Производительность делегирования

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

Простейший пример делегирования выглядит следующим образом:

tippy.delegate(document.body, {
  target: '.has-tooltip',
  content(reference) {
    return reference.getAttribute('data-tooltip');
  },
  delay: 100,
  placement: 'top'
});

Пояснения:

  • delegate(root, options) — корневой метод для делегирования, где root — контейнер, в котором будут работать подсказки.
  • target — CSS-селектор для дочерних элементов, на которые будут навешены тултипы.
  • content — функция, возвращающая текст подсказки для конкретного элемента. Аргумент reference — элемент DOM, на котором возникло событие.
  • delay и placement управляют временем появления и расположением подсказки относительно целевого элемента.

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


Влияние делегирования на производительность

Создание множества отдельных инстансов Tippy.js может существенно замедлять работу страницы. Каждый отдельный вызов tippy(element, options) создает отдельный объект с собственными слушателями событий. При сотнях или тысячах элементов это становится критично.

Использование tippy.delegate:

  • Создает один обработчик на родителе вместо множества слушателей.
  • Уменьшает количество объектов в памяти, так как все тултипы управляются единым делегированным объектом.
  • Обеспечивает поддержку динамически добавляемых элементов без пересоздания тултипов.

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


Настройка делегированных тултипов

Контент через атрибуты

Самый удобный способ — хранить текст подсказки в data- атрибуте элемента.

<button class="has-tooltip" data-tooltip="Сохранить изменения">Сохранить</button>
<button class="has-tooltip" data-tooltip="Удалить запись">Удалить</button>
tippy.delegate(document.body, {
  target: '.has-tooltip',
  content(reference) {
    return reference.dataset.tooltip;
  },
  placement: 'right',
  animation: 'shift-away',
  theme: 'light-border'
});

Такой подход отделяет логику интерфейса от контента тултипа, что упрощает поддержку и масштабирование.

Фильтрация элементов

Можно использовать функцию target вместо строки-селектора для более сложных условий:

tippy.delegate(document.body, {
  target(reference) {
    return reference.matches('.has-tooltip') && reference.dataset.active === 'true';
  },
  content(reference) {
    return reference.dataset.tooltip;
  }
});

Это позволяет показывать тултипы только для определенных элементов в зависимости от состояния.


Делегирование с динамическим контентом

При работе с AJAX-загрузками или динамическим рендерингом компонентов делегирование полностью исключает необходимость пересоздавать тултипы.

const container = document.getElementById('dynamic-list');

tippy.delegate(container, {
  target: '.has-tooltip',
  content(reference) {
    return reference.dataset.tooltip;
  }
});

// Динамически добавляем элемент
const newItem = document.createElement('button');
newItem.className = 'has-tooltip';
newItem.dataset.tooltip = 'Новый элемент';
newItem.textContent = 'Новый';
container.appendChild(newItem);

Даже после добавления нового элемента подсказка появится автоматически.


Продвинутые настройки производительности

  • delay — уменьшение или увеличение задержки появления может сократить количество лишних событий при быстром движении курсора.
  • maxWidth — ограничение ширины тултипа снижает нагрузку на браузер при сложных или длинных подсказках.
  • hideOnClick — отключение автоматического скрытия для часто обновляемых элементов предотвращает лишние пересоздания тултипов.
  • lazy — отложенная инициализация тултипа только при первом наведении.
tippy.delegate(document.body, {
  target: '.has-tooltip',
  content(reference) {
    return reference.dataset.tooltip;
  },
  lazy: true,
  maxWidth: 200
});

Использование lazy: true особенно важно для больших списков, где сотни элементов могут не нуждаться в тултипе до фактического взаимодействия.


События делегированных тултипов

Делегированные тултипы поддерживают все стандартные события Tippy.js:

  • onShow(instance) — вызывается при отображении подсказки.
  • onHide(instance) — вызывается при скрытии.
  • onMount(instance) — после монтирования DOM-элемента подсказки.
  • onUntriggered(instance) — когда указатель уходит с элемента до полного появления.

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

tippy.delegate(document.body, {
  target: '.has-tooltip',
  content(reference) {
    return reference.dataset.tooltip;
  },
  onShow(instance) {
    console.log('Показан тултип для', instance.reference.textContent);
  }
});

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


Рекомендации по использованию делегирования

  1. Всегда использовать делегирование для больших наборов элементов (100+) или динамически создаваемых элементов.
  2. Хранить контент в data- атрибутах для простоты и производительности.
  3. Настраивать lazy, delay и maxWidth для оптимизации рендеринга.
  4. Использовать функции target и content для гибкой фильтрации и динамического контента.
  5. Управлять событиями делегированных тултипов через стандартные обработчики onShow, onHide, onMount для тонкой настройки взаимодействия.

Делегирование событий в Tippy.js сочетает эффективность, гибкость и простоту поддержки, делая его незаменимым инструментом для современных интерфейсов с большим количеством интерактивных элементов.