我正在查看检查元素是否重叠的许多答案,但是它们不适用。
我有一个包装器组件,该组件的标头具有固定的位置和子级
const Wrapper = ({ children }) => {
return (
<>
<Header/>
{children}
</>
)
};
export default Wrapper
我需要知道标题何时与几个不同页面(子级)中的某些部分重叠,以更改标题颜色
我正在尝试在包装器组件中进行检测,但是元素不存在或不能被容器使用
我是否需要将引用从包装器一直传递给所有孩子?有没有更简单的方法可以做到这一点?
谢谢
我可以想到几种方法,一种是您提到的方法,将引用传递给周围并进行大量计算,下面还有其他一些方法。
这基本上可以通过在头文件中放置一个大的开关盒并检查滚动目标的偏移滚动位置来工作。
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。 (请注意:此代码段只是为了证明概念,需要tweek的时间。)
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));
};
}, []);
也请注意,这并不是最“反应”的处理方式,因为它很大程度上依赖于ids
,但是您可以通过在我使用dom选择的所有地方传递引用来解决这个问题,但这可能变得笨拙。