检查元素是否在 React.js 的视口中

在 React.js 中检查元素是否在视口中

Check if an Element is in the Viewport in React.js

在 React.js 中检查元素是否在视口中:

  1. ref在元素上设置道具。
  2. 使用IntersectionObserverAPI 跟踪元素是否相交。
应用程序.js
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 只跟踪单个元素(我们设置 的元素ref)。

我们调用了observe()将我们要跟踪的元素传递给它的方法 –
observer.observe(ref.current)

每次元素进入视口或存在视口时,我们传递给IntersectionObserver()构造函数的函数都会被调用,我们会更新状态。

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

ref如果我们设置对象
的元素在视口中,
useIsInViewport钩子将返回true

如果该元素不在视口中,则挂钩返回false

请注意,在初始渲染时,useIsInViewport钩子将返回 false,因为这是我们传递给useState
的初始值
const [isIntersecting, setIsIntersecting] = useState(false);

如果要跟踪挂钩返回值的更改,请使用
useEffect挂钩并将该值添加到挂钩的依赖项中。

应用程序.js
const isInViewport1 = useIsInViewport(ref1); console.log('isInViewport1: ', isInViewport1); useEffect(() => { // 👇️ listen for changes console.log(isInViewport1); }, [isInViewport1]);