【问题标题】:React: check if elements in different components overlapReact:检查不同组件中的元素是否重叠
【发布时间】:2020-05-06 23:40:17
【问题描述】:

我正在查看许多检查元素是否重叠的答案,但它们不适用。

我有一个包装器组件,它有一个位置固定的标题和子组件

const Wrapper = ({ children }) => {

  return (
    <>
    <Header/>
    {children}
    </>
  )
};

export default Wrapper

我需要知道标题何时与几个不同页面(子页面)中的某些部分重叠,以便更改标题颜色

我试图在包装器组件中检测,但元素不存在或容器不可访问

我是否需要将 refs 从包装器一路传递给所有子级?有没有更简单的方法来做到这一点?

谢谢

【问题讨论】:

    标签: reactjs overlap ref


    【解决方案1】:

    我能想到几种方法,一种是您提到的方法,然后传递参考并进行大量计算,下面还有一些其他方法。

    页面的硬编码高度

    这基本上可以通过在你的头文件中有一个大的开关盒并检查你的滚动目标的偏移滚动位置来工作。

    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 是一个很棒的 AP​​I,它允许您以高效的方式观察元素,并通过持续测量减少其他方式的布局抖动 这是我用反应和交叉观察者做的一个例子,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 来解决这个问题,但这可能会变得笨拙。

    【讨论】:

    • 感谢您的详细回复。
    猜你喜欢
    • 2021-06-08
    • 1970-01-01
    • 2013-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2017-04-25
    • 2020-03-07
    相关资源
    最近更新 更多