reloadOnContextChange

Библиотека Locomotive Scroll обеспечивает плавный скролл с возможностью отслеживания положения элементов на странице и управления эффектами на основе прокрутки. Одной из важных опций является reloadOnContextChange, которая управляет пересчётом внутренних данных при изменении контекста страницы или DOM-структуры.

Инициализация Locomotive Scroll осуществляется следующим образом:

import LocomotiveScroll from 'locomotive-scroll';

const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true,
  smartphone: {
    smooth: true
  },
  tablet: {
    smooth: true
  },
  reloadOnContextChange: true
});

Здесь ключевой параметр:

  • reloadOnContextChange: true — автоматически пересчитывает размеры элементов и позиции скролла, если DOM был изменён динамически (например, добавлены новые блоки или изменился контент).

Механизм работы reloadOnContextChange

По умолчанию Locomotive Scroll кэширует позиции элементов для повышения производительности. Когда структура DOM изменяется, позиции могут устаревать. Параметр reloadOnContextChange решает эту проблему:

  1. Отслеживает изменения в элементе-контейнере (el).
  2. Использует MutationObserver для выявления изменений в DOM.
  3. Пересчитывает внутренние размеры и позиции элементов.
  4. Обеспечивает корректное срабатывание скролл-триггеров, анимаций и эффектов, связанных с прокруткой.

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

Практическое использование

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

Если на страницу добавляются новые секции через Jav * aScript:

const newSection = document.createElement('section');
newSection.setAttribute('data-scroll-section', '');
newSection.innerHTML = '

Новая секция

'; document.querySelector('[data-scroll-container]').appendChild(newSection);

С включённым reloadOnContextChange: true Locomotive Scroll автоматически пересчитает позиции и обновит скролл, чтобы новая секция корректно реагировала на скролл.

Ручной пересчёт

Даже при активной опции иногда требуется явно пересчитать скролл:

scroll.update();

Это вызовет пересчёт всех размеров и позиций элементов, аналогично тому, как это делает автоматический reloadOnContextChange.

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

Использование reloadOnContextChange создаёт дополнительную нагрузку, так как MutationObserver отслеживает все изменения в DOM контейнера. Рекомендуется:

  • Ограничивать область наблюдения с помощью селектора контейнера.
  • Не добавлять и не удалять большое количество элементов одновременно.
  • При необходимости отключать reloadOnContextChange для статических страниц.
const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true,
  reloadOnContextChange: false
});

В этом случае динамический контент потребует ручного вызова scroll.update().

Совместимость с фреймворками

  1. React: при использовании reloadOnContextChange скролл корректно реагирует на ререндер компонента, где меняется контент.
  2. Vue: при динамическом добавлении элементов через v-for пересчёт выполняется автоматически.
  3. Svelte: обновления DOM отслеживаются и пересчёт выполняется без дополнительного кода.

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

Отслеживание событий скролла

Даже с динамическим контентом события остаются актуальными:

scroll.on('scroll', (args) => {
  console.log(args.scroll.y); // текущая позиция прокрутки
});

scroll.on('call', (func, way, obj) => {
  console.log(func, way, obj);
});

reloadOnContextChange гарантирует, что новые элементы, добавленные в DOM, будут участвовать в этих событиях без дополнительных действий.

Особенности взаимодействия с анимациями

При использовании библиотек вроде GSAP или CSS-анимаций на основе данных скролла, пересчёт позиций крайне важен. Без reloadOnContextChange анимации могут запускаться не в том месте или с ошибкой синхронизации.

gsap.from('[data-scroll]', {
  y: 50,
  opacity: 0,
  scrollTrigger: {
    scroller: '[data-scroll-container]',
    trigger: '[data-scroll]',
    start: 'top 80%',
    end: 'bottom 20%',
    scrub: true
  }
});

Включённая опция автоматически обновляет позиции триггеров при изменении DOM, что предотвращает баги.