繁体   English   中英

Reactjs 中的交叉点观察器

[英]Intersection Observer in Reactjs

有人可以帮助我如何在 Reactjs 中做到这一点吗?

我可以在 reactjs 中为多个孩子迭代一个 IntersectionObserver

 const faders = document.querySelectorAll('.fade-in'); const appearOptions = { threshold: 1 }; const appearOnScroll = new IntersectionObserver( function(entries, appearOnScroll){ entries.forEach(entry => { if(!entry.isIntersecting){ return; }else{ entry.target.classList.add('appear') appearOnScroll.unobserve(entry.target) } }) }, appearOptions); faders.forEach(fader =>{ appearOnScroll.observe(fader) })

使用IntersectionObserver.js

使用这个自定义钩子。 它创建一个IntersectionObserver实例并将其保存在useRef挂钩中。 它跟踪在某个状态下观察到的元素。 每当状态发生变化时,它不会观察所有元素,然后重新观察保持在状态中的元素。

创建自定义钩子的优点是您可以重复使用该钩子并在多个场合实现它。

import { useRef, useState, useEffect } from 'react';

const useIntersectionObserver = ({ root = null, rootMargin = '0px', threshold = 0 }) => {
  const [entries, setEntries] = useState([]);
  const [observedNodes, setObservedNodes] = useState([]);
  const observer = useRef(null);

  useEffect(() => {
    if (observer.current) {
      observer.current.disconnect();
    }

    observer.current = new IntersectionObserver(entries => setEntries(entries), {
      root,
      rootMargin,
      threshold
    });

    const { current: currentObserver } = observer;

    for (const node of observedNodes) {
      currentObserver.observe(node);
    }

    return () => currentObserver.disconnect();
  }, [observedNodes, root, rootMargin, threshold]);


  return [entries, setObservedNodes];
};

export default useIntersectionObserver;

应用程序.js

在需要观察元素的地方使用钩子。 创建对您需要观察的元素的引用,并在第一次渲染后将它们传递给钩子。

entries状态将包含一个IntersectionObserverEntry对象数组。 每当entries状态更改并断言您的逻辑时,循环它,例如添加一个类。

import { useRef, useEffect } from 'react';
import useIntersectionObserver from './useIntersectionObserver';

function App() {
  const targets = useRef(new Set());

  const [entries, setObservedNodes] = useIntersectionObserver({
    threshold: 1
  });

  useEffect(() => {
    setObservedNodes(() => ([...targets.current]));
  }, [setObservedNodes]);

  useEffect(() => {
    for (const entry of entries) {
      if (entry.isIntersecting) {
        entry.target.classList.add('appear');

        setObservedNodes(observedNodes => 
          observedNodes.filter(node => node !== entry.target)
        );
      }
    }
  }, [entries, setObservedNodes]);

  return (
    <>
      <div className="fade-in" ref={element => targets.current.add(element)}></div>
      <div className="fade-in" ref={element => targets.current.add(element)}></div>
    </>
  )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM