资讯动态

react-use 的 useIntersection:用 Intersection Observer API 感知元素可见性

发布时间:2026/9/19 2:12:25 来源:尧图企业网站定制
react-use 的 useIntersection用 Intersection Observer API 感知元素可见性【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use导读useIntersection是 react-use 提供的一个传感器Sensor类 React Hook它封装了浏览器原生的 Intersection Observer API用于实时追踪目标元素与祖先元素或顶级文档视口之间的交叉intersection变化并返回最新的IntersectionObserverEntry对象。本文将以 docs/useIntersection.md 为核心结合仓库中的源码实现、单元测试与 Storybook 示例讲解该 Hook 的用法、参数语义、运行机制与边界行为帮助你用十几行代码实现元素是否进入视口滚动到某处触发加载曝光埋点等典型场景。什么是 useIntersection在 react-use 的 Sensor Hooks 体系参见 docs/Sensors.md中useIntersection负责监听某个界面事件并驱动组件以最新状态重新渲染。它跟踪的是目标元素与某个祖先元素或顶级文档视口之间的交叉情况底层完全建立在浏览器原生的 Intersection Observer API 之上。其核心特性如下跟踪目标元素与根元素root之间的交叉区域变化返回值为IntersectionObserverEntry或其null变体可直接读取intersectionRatio、isIntersecting等字段无需手动维护 observer 的创建、观察与断开全部由 Hook 内部管理依赖数组对ref.current与关键选项进行监听目标元素或选项变化时会自动重建 observer。函数签名useIntersection( ref: RefObjectHTMLElement, options: IntersectionObserverInit, ): IntersectionObserverEntry | null;ref指向目标 DOM 元素的RefObjectHTMLElement。当ref.current尚未绑定元素例如组件首次渲染时或元素不存在时Hook 返回null。options原生IntersectionObserverInit配置对象包括root、rootMargin与threshold详见下文参数说明。返回值最新一次的IntersectionObserverEntry在 observer 尚未触发任何回调、目标元素缺失或浏览器不支持 IntersectionObserver 时为null。快速上手安装react-use 以 npm 包形式分发可通过 yarn 或 npm 安装yarn add react-use # 或 npm install react-use从源码结构看包通过 src/index.ts 的export { default as useIntersection } from ./useIntersection;对外导出因此可直接命名导入import { useIntersection } from react-use;基础示例判断元素是否完整可见以下示例直接取自 docs/useIntersection.md创建一个始终引用目标元素的 ref并把threshold设为1要求 100% 可见才视为完整在视口内import * as React from react; import { useIntersection } from react-use; const Demo () { const intersectionRef React.useRef(null); const intersection useIntersection(intersectionRef, { root: null, rootMargin: 0px, threshold: 1 }); return ( div ref{intersectionRef} {intersection intersection.intersectionRatio 1 ? Obscured : Fully in view} /div ); };当元素被滚动遮挡时intersectionRatio会小于1界面显示Obscured元素完整进入视口后显示Fully in view。注意intersection初始为null因此渲染分支中要先做intersection 的空值判断。带滚动容器的完整演示仓库中的 Storybook 示例 stories/useIntersection.story.tsx 给出了一个更接近真实布局的用法外层是一个可滚动的div充当交叉区域目标元素嵌套在多个占位块之间滚动外层容器即可看到目标元素在Obscured与Fully in view之间切换const Demo () { const intersectionRef React.useRef(null); const intersection useIntersection(intersectionRef, { root: null, rootMargin: 0px, threshold: 1, }); return ( div style{{ width: 400px, height: 400px, backgroundColor: whitesmoke, overflow: scroll, }} Scroll me Spacer / div ref{intersectionRef} style{{ width: 100px, height: 100px, padding: 20px, backgroundColor: palegreen, }} {intersection intersection.intersectionRatio 1 ? Obscured : Fully in view} /div Spacer / /div ); };该 Story 同时演示了Docs页通过ShowDocs渲染docs/useIntersection.md原文是理解本 Hook 行为的最佳交互式参考。你可以在仓库根目录运行yarn storybook对应 package.json 中的start/storybook脚本默认端口 6008后在Sensors/useIntersection分组下查看。options 参数详解useIntersection的第二个参数直接透传给原生IntersectionObserver因此其语义与浏览器规范一致参数类型默认值说明rootElement \| Document \| nullnull作为视口的祖先元素null表示使用顶级文档视口浏览器 viewport。交叉区域的计算以该元素为边界rootMarginstring0px围绕根元素的 margin写法与 CSS margin 一致如10px、0px 20px可扩大或缩小交叉判定区域thresholdnumber \| number[]0可见比例阈值取值0到1。传入数组如[0, 0.25, 0.5, 1]时每当可见比例跨过其中任一值都会触发一次回调需要注意与原生 API 的默认值不同文档示例中通常显式写出root: null与rootMargin: 0px这样能保证跨浏览器行为一致。源码实现与运行机制useIntersection的完整实现位于 src/useIntersection.ts仅有约 28 行其运行逻辑可以拆解为以下几步。状态管理Hook 使用useStateIntersectionObserverEntry | null保存最近一次交叉回调带来的 entryconst [intersectionObserverEntry, setIntersectionObserverEntry] useStateIntersectionObserverEntry | null(null);初始值为null这与尚未产生任何交叉数据的语义一致也解释了为何返回值类型包含null。observer 的创建与清理在useEffect中Hook 首先检查ref.current是否存在、以及浏览器是否支持IntersectionObserveruseEffect(() { if (ref.current typeof IntersectionObserver function) { const handler (entries: IntersectionObserverEntry[]) { setIntersectionObserverEntry(entries[0]); }; const observer new IntersectionObserver(handler, options); observer.observe(ref.current); return () { setIntersectionObserverEntry(null); observer.disconnect(); }; } return () {}; }, [ref.current, options.threshold, options.root, options.rootMargin]);几个值得注意的实现细节回调只取第一条 entryIntersection Observer 的回调会收到一个 entry 数组而本 Hook 只观察了一个目标元素因此直接取entries[0]并写入 state从而触发组件重新渲染useEffect 返回清理函数每次 effect 重跑前都会执行setIntersectionObserverEntry(null)重置状态并调用observer.disconnect()断开旧的 observer避免内存泄漏依赖数组精挑细选依赖项为ref.current与options.threshold、options.root、options.rootMargin而非整个options对象。从源码结构看这是为了在传入内联对象字面量时避免因引用变化而无谓地重建 observer与此同时这也意味着修改options上的其他字段不会被感知实际使用时应只变更这四个受监听的关键配置能力检测typeof IntersectionObserver function的守卫确保在不支持该 API 的浏览器环境中安全降级此时 Hook 不做任何观察、返回null不会抛错。目标元素与配置变化时的行为由于依赖数组的存在当发生以下任一情况时Hook 会断开旧 observer、清空 entry 并针对新的目标或配置重新建立 observerref.current从无到有、从有到无、或切换到另一个 DOM 元素threshold、root或rootMargin任一值变化。这一点在下文的测试用例中得到了充分验证。边界行为来自单元测试的证据仓库中的 tests/useIntersection.test.tsx 使用shopify/jest-dom-mocks模拟了 Intersection Observer并通过renderHook验证了本 Hook 的关键边界行为可以作为理解其语义的权威参考场景测试结论目标元素存在会创建一个 observer其target与options分别等于传入的ref.current与选项对象ref.current为null返回null且不会创建 observerobserver 触发交叉回调返回第一个IntersectionObserverEntry测试中模拟了intersectionRatio: 0.81、isIntersecting: true等字段目标元素变化旧 entry 被重置为null并针对新元素创建新的 observer选项变化旧的 observer 被替换新的 observer 携带最新选项浏览器不支持 IntersectionObserver不抛异常安全降级返回nullref 变化导致的清理disconnect被正确调用observer 实例不会泄漏其中目标元素变化时 entry 被重置为null这一点尤其值得注意当你在列表渲染中复用同一个 Hook 而目标元素切换时界面不会短暂地显示上一个元素的交叉状态而是回到未知状态这避免了错误的可见性判断。典型实战场景基于上述 API 与行为useIntersection可快速实现以下常见需求图片/内容懒加载监听目标占位元素当intersectionRatio 0或isIntersecting为真时再加载真实资源无限滚动在列表底部放置一个哨兵元素进入视口即触发下一页数据请求曝光埋点元素可见比例超过阈值如 50%时上报一次曝光事件吸顶/动画触发根据intersectionRatio判断元素被遮挡程度动态切换样式或播放动画阅读进度提示组合threshold: [0, 0.25, 0.5, 0.75, 1]数组获得更细粒度的可见比例回调。注意事项浏览器兼容性本 Hook 依赖原生 Intersection Observer API不支持的环境如部分旧版移动端浏览器下会静默返回null。需要全兼容时可自行在应用层引入 polyfilloptions对象引用依赖数组只监听threshold、root、rootMargin三个字段更新options中的其他属性不会被响应初始为null渲染时必须处理intersection null的情况如显示占位内容避免读取intersection.intersectionRatio报错服务端渲染SSR由于依赖浏览器 API在 SSR 环境下 effect 不会执行Hook 返回null这与项目提供的test:ssr测试脚本见 package.json所覆盖的整体策略一致。小结useIntersection是 react-use 中封装度极高、实现极简约 28 行源码的传感器 Hook它把 Intersection Observer 的创建、观察、状态同步与清理全部收敛进一个 Hook 中并妥善处理了目标元素缺失、浏览器不支持、选项变更等边界场景。无论是滚动驱动的可见性判断还是懒加载与曝光埋点都可以通过本文的示例与参数说明直接落地到业务代码中。如需深入验证其行为可结合 src/useIntersection.ts、tests/useIntersection.test.tsx 与 stories/useIntersection.story.tsx 一起阅读。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价