我能想到几种方法,一种是您提到的方法,然后传递参考并进行大量计算,下面还有一些其他方法。
页面的硬编码高度
这基本上可以通过在你的头文件中有一个大的开关盒并检查你的滚动目标的偏移滚动位置来工作。
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'
}
}
这有明显的缺陷,一个是,如果页面内容是动态的或经常更改可能无法正常工作,每次重新渲染时检查高度可能会导致回流问题,这需要了解页面上的页面 ID。 (注意:这个 sn-p 只是为了证明概念,它需要 tweeks)。
路口观察者(推荐方式)
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 选择的任何地方传递 refs 来解决这个问题,但这可能会变得笨拙。