Обновление waypoints при изменении DOM

Библиотека Waypoints отслеживает позиции элементов на странице и выполняет функции при достижении определённых точек прокрутки. Важная особенность — Waypoints вычисляет координаты элементов один раз при инициализации. Если DOM меняется после этого (добавление, удаление, изменение размеров элементов), позиции точек могут устареть. Без обновления Waypoints срабатывания могут происходить некорректно или вовсе не происходить.


Когда необходимо обновление

Обновление нужно в следующих случаях:

  1. Добавление новых элементов, которые должны иметь свои Waypoints.
  2. Изменение размеров элементов (например, динамическое изменение контента через JS или CSS анимации).
  3. Изменение положения элементов, вызванное вставкой/удалением блоков выше по странице.
  4. Асинхронная загрузка контента (AJAX, fetch), когда элементы появляются после загрузки страницы.

Если игнорировать обновление, Waypoints будет использовать старые значения offset и top, что приведёт к ошибкам при срабатывании событий.


Методы обновления Waypoints

Waypoints предоставляет встроенные методы для корректного пересчёта точек:

1. Waypoint.refreshAll()

Метод пересчитывает координаты всех существующих Waypoints. Используется при массовых изменениях DOM.

Пример:

// После динамического добавления элементов
Waypoint.refreshAll();

Особенности:

  • Применяется к всем Waypoints на странице.
  • Автоматически учитывает новые размеры и смещения элементов.
  • Эффективен после вставки или удаления блоков, изменения высоты контейнеров.

2. Waypoint.disable() и Waypoint.enable()

Для точечных изменений можно временно отключить Waypoint, а затем включить после перестроения DOM:

var waypoint = new Waypoint({
  element: document.getElementById('section1'),
  handler: function(direction) {
    console.log('Section reached: ' + direction);
  }
});

waypoint.disable(); // отключение
// изменения DOM
waypoint.enable();  // повторное включение

Используется для предотвращения ложных срабатываний во время активных изменений на странице.


Обновление при динамических событиях

Подписка на события изменения DOM

Для автоматического пересчёта можно использовать MutationObserver:

const observer = new MutationObserver(function(mutationsList, observer) {
  Waypoint.refreshAll();
});

observer.observe(document.body, { 
  childList: true, 
  subtree: true,
  attributes: true,
  characterData: true
});

Пояснение:

  • childList: true — отслеживает добавление или удаление узлов.
  • subtree: true — включает все вложенные элементы.
  • attributes: true — отслеживает изменения атрибутов.
  • characterData: true — отслеживает текстовые изменения.

Такой подход позволяет Waypoints автоматически корректировать свои позиции без ручного вызова refreshAll после каждого изменения DOM.


Работа с ленивой загрузкой и AJAX

При динамической загрузке контента:

fetch('/api/content')
  .then(res => res.text())
  .then(html => {
    const container = document.getElementById('content');
    container.innerHTML += html;
    Waypoint.refreshAll(); // пересчёт Waypoints после вставки нового контента
  });

Важно: вызов refreshAll() после добавления элементов в DOM гарантирует правильное срабатывание событий.


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

  1. Не вызывать refreshAll слишком часто при мелких изменениях, чтобы не перегружать браузер.
  2. Для частых изменений лучше группировать изменения и вызывать refreshAll один раз после завершения всех модификаций.
  3. Если известно, что изменения касаются только одного Waypoint, можно использовать enable() / disable() вместо массового пересчёта.
  4. При большом количестве Waypoints использовать requestAnimationFrame или setTimeout для асинхронного вызова refreshAll, чтобы избежать блокировки интерфейса.

Совместимость с jQuery

Waypoints интегрируется с jQuery. При изменении DOM через jQuery методы работают аналогично:

$('#container').append('<div class="section"></div>');
Waypoint.refreshAll();

Можно также использовать события jQuery для отслеживания вставки элементов:

$('#container').on('DOMNodeInserted', function() {
  Waypoint.refreshAll();
});

Однако MutationObserver предпочтительнее, так как DOMNodeInserted устарел и может работать медленнее.


Итоговая структура использования

  1. Инициализация Waypoints.
  2. Динамические изменения DOM (добавление, удаление, изменение размеров).
  3. Вызов Waypoint.refreshAll() после завершения изменений.
  4. Опционально: использование disable() / enable() для точечных Waypoints.
  5. При частых изменениях — MutationObserver для автоматического обновления.

Эти методы позволяют поддерживать корректное поведение Waypoints на страницах с динамическим контентом и сложной версткой.