关于react.js:React技巧之检查元素是否可见

2次阅读

共计 1953 个字符,预计需要花费 5 分钟才能阅读完成。

原文链接:https://bobbyhadz.com/blog/react-check-if-element-in-viewport

作者:Borislav Hadzhiev

注释从这开始~

总览

在 React 中,查看元素是否在视口范畴内:

  1. 在元素上设置 ref 属性。
  2. 应用IntersectionObserver API 来跟踪元素是否与视口相交。
import {useEffect, useRef, useState, useMemo} from 'react';

export default function App() {const ref1 = useRef(null);
  const ref2 = useRef(null);

  const isInViewport1 = useIsInViewport(ref1);
  console.log('isInViewport1:', isInViewport1);

  const isInViewport2 = useIsInViewport(ref2);
  console.log('isInViewport2:', isInViewport2);

  return (
    <div>
      <div ref={ref1}>Top div {isInViewport1 && '| in viewport ✅'}</div>

      <div style={{height: '155rem'}} />

      <div ref={ref2}>Bottom div {isInViewport2 && '| in viewport ✅'}</div>
    </div>
  );
}

function useIsInViewport(ref) {const [isIntersecting, setIsIntersecting] = useState(false);

  const observer = useMemo(() =>
      new IntersectionObserver(([entry]) =>
        setIsIntersecting(entry.isIntersecting),
      ),
    [],);

  useEffect(() => {observer.observe(ref.current);

    return () => {observer.disconnect();
    };
  }, [ref, observer]);

  return isIntersecting;
}

该示例向咱们展现了,如何查看元素是否在视口范畴内。IntersectionObserver API 使咱们可能查看一个给定的元素是否与文档相交。

useIsInViewport钩子接管一个指向咱们想要追踪的元素的 ref 对象。

IntersectionObserver

IntersectionObserver构造函数接管一个函数,该函数被调用时带有一个 entry 数组。entry是一个数组,其蕴含了所有的 obeserver 的指标元素。这些元素的可见度曾经高于或低于 intersection observer 的比率之一。

每个 entry 都形容了一个给定元素与根元素(文档)相交的水平。咱们解构了这个 entry,因为咱们的IntersectionObserver 只能跟踪一个元素(就是咱们设置 ref 的那个元素)。

咱们调用 observe() 办法,将咱们要跟踪的元素传给它 – observer.observe(ref.current)

每当元素进入视口或者存在于视口中时,咱们传递给 IntersectionObserver() 构造函数的函数就会被调用,而后更新 state 变量。

// 👇️ gets called every time element enters or leaves viewport
new IntersectionObserver(([entry]) =>
  setIsIntersecting(entry.isIntersecting),
)

如果咱们设置 ref 对象的元素在视口中,useIsInViewport钩子将会返回true。如果元素不在视口中,该钩子将会返回false

须要留神的是,在初始渲染时,useIsInViewport 钩子将会返回 false。因为咱们为useState 传递的初始值为falseconst [isIntersecting, setIsIntersecting] = useState(false);

如果你想跟踪钩子的返回值的变动,请应用 useEffect 钩子,并将该值增加到钩子的依赖关系中。

const isInViewport1 = useIsInViewport(ref1);
console.log('isInViewport1:', isInViewport1);

useEffect(() => {
  // 👇️ listen for changes
  console.log(isInViewport1);
}, [isInViewport1]);
正文完
 0