есть несколько подходов, которые я могу придумать, один из которых - это тот, который вы упомянули, передавая ссылки и выполняя кучу вычислений, а также несколько других ниже.
Жестко заданные высоты страниц
Это будет работать в основном за счет наличия большого переключателя в вашем файле заголовка и проверки позиции прокрутки смещения вашей цели прокрутки.
getBackgroundColor = (scrollPosition) => {
switch (true) {
case scrollPosition <= $('#page1').height:
return 'red'
case scrollPosition <= $('#page1').height + $('#page2').height:
return 'blue'
case scrollPosition <= $('#page1').height + $('#page2').height + $('page3').height
return 'green'
default:
return 'yellow'
}
}
Это имеет очевидный fl aws, один из которых, если страница содержимое динамически c или часто изменяется, оно может не работать, проверка высоты при каждом повторном рендеринге может вызвать проблемы с перекомпоновкой, а для этого требуется знание идентификаторов страниц на странице. (примечание: этот фрагмент предназначен только для подтверждения концепции, он потребует дополнительных настроек).
Intersection Observer (рекомендуемый способ)
Intersection Observer - отличный API, который позволяет вам для эффективного наблюдения за элементами и уменьшения потери макета по сравнению с альтернативными способами с постоянными измерениями. Вот пример, который я сделал с наблюдателем реакции и пересечения, https://codesandbox.io/s/relaxed-spence-yrozp. Это может быть не лучшим вариантом, если у вас есть сотни целей, но я не проводил никаких тестов, поэтому не уверен. Также он считается «экспериментальным», но имеет хорошую поддержку браузером (не IE).
вот основная часть кодов и поле ниже, чтобы получить представление.
React.useEffect(() => {
let headerRect = document.getElementById("header").getBoundingClientRect();
let el = document.getElementById("wrapper");
let targets = [...document.getElementsByClassName("block")];
let callback = (entries, observer) => {
entries.forEach(entry => {
let doesOverlap = entry.boundingClientRect.y <= headerRect.bottom;
if (doesOverlap) {
let background = entry.target.style.background;
setColor(background);
}
});
};
let io = new IntersectionObserver(callback, {
root: el,
threshold: [0, 0.1, 0.95, 1]
});
targets.forEach(target => io.observe(target));
return () => {
targets.forEach(target => io.unobserve(target));
};
}, []);
Также обратите внимание это не самый "React" способ делать что-либо, поскольку он во многом полагается на ids
, но вы можете обойти это, передавая ссылки везде, где я использовал выборку dom, но это может стать громоздким.