React可滚动modal如何识别当前可视元素并更新对应elm变量
实现方案
核心采用浏览器原生IntersectionObserver接口实现可视元素检测,相比手动计算滚动位置的方案,准确率更高、兼容性更好,也能避免布局偏移导致的计算误差。
import { useState, useRef, useEffect } from 'react' const Modal = (props) => { const [elm, setElm] = useState(0) // 存储所有待检测元素的ref const itemRefs = useRef([]) // 滚动容器ref const scrollContainerRef = useRef(null) useEffect(() => { const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const index = itemRefs.current.indexOf(entry.target) if (index !== -1 && entry.intersectionRatio >= 0.5) { // 元素可见比例超过50%时更新序号,阈值可自行调整 setElm(index) } } }) }, { root: scrollContainerRef.current, threshold: [0, 0.5, 1] }) itemRefs.current.forEach(item => item && observer.observe(item)) return () => observer.disconnect() }, []) return ( <div ref={scrollContainerRef} style={{ height: '400px', overflowY: 'auto', border: '1px solid #eee' }} > <p>Current element is: {elm}</p> <div ref={el => itemRefs.current[0] = el}>element1 内容</div> <div ref={el => itemRefs.current[1] = el}>element2 内容</div> <div ref={el => itemRefs.current[2] = el}>element3 内容</div> <div ref={el => itemRefs.current[3] = el}>element4 内容</div> </div> ) }
注意事项
- 自定义可见规则可调整
threshold参数与intersectionRatio判断阈值,如需元素完全可见才更新,将阈值设为1即可 - 动态元素可在遍历渲染时绑定ref,无需手动逐个指定序号
- 如果element1~element4是自定义函数组件,需要使用
forwardRef包裹组件接收ref参数,否则无法绑定DOM节点 - 若仍要使用手动计算滚动位置的方案,需保证滚动容器为定位元素(添加
position: relative属性),计算时取scrollTop + 容器可视高度/2与各元素offsetTop值对比,取最接近的值对应序号即可
内容的提问来源于stack exchange,提问作者Mladen Milosavljevic
相关产品推荐
相关产品推荐

