滚动列表时动态切换元素flag状态的实现方案咨询
实现滚动容器内可见元素的flag属性切换为true的方案
可以通过Intersection Observer API实现这个需求,它能高效监听元素是否进入滚动容器的可视区域,相比传统scroll事件性能更优,不会因频繁触发导致页面卡顿。
实现步骤及代码示例
- 将数组转为React状态,确保更新flag时能触发组件重渲染
- 创建Intersection Observer实例,指定滚动容器为观察根节点
- 为每个列表元素添加观察,在元素可见性变化时更新对应的flag值
完整代码如下:
import { useEffect, useState, useRef } from 'react'; export default function App() { // 将数组转为状态,便于更新flag触发重渲染 const [arr, setArr] = useState([ { id: 2, flag: true }, { id: 3, flag: false }, { id: 4, flag: false }, { id: 5, flag: false }, { id: 6, flag: false }, { id: 7, flag: false }, { id: 8, flag: false }, { id: 9, flag: false }, { id: 10, flag: false }, { id: 11, flag: false }, { id: 12, flag: false }, { id: 13, flag: false }, { id: 14, flag: false }, ]); const scrollContainerRef = useRef(null); useEffect(() => { if (!scrollContainerRef.current) return; // 创建Intersection Observer实例 const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { // 获取元素对应的id const itemId = Number(entry.target.dataset.id); // 更新对应元素的flag值 setArr(prev => prev.map(item => item.id === itemId ? {...item, flag: entry.isIntersecting} : item )); }); }, { root: scrollContainerRef.current, // 指定滚动容器为观察根节点 threshold: 0.1 // 元素可见比例达到10%时触发回调 } ); // 为每个列表元素添加观察 document.querySelectorAll('.list-item').forEach(item => { observer.observe(item); }); // 组件卸载时停止观察 return () => observer.disconnect(); }, []); return ( <div ref={scrollContainerRef} style={{ width: '100px', overflow: 'scroll', height: '60px', }} > {arr.map((el) => ( <div key={el.id} className="list-item" data-id={el.id}> <div style={{backgroundColor: `${el.flag ? 'green' : 'red'}`, margin: '5px 0'}}> {el.id} </div> </div> ))} </div> ); }
关键说明
- Intersection Observer配置:
root参数指定了滚动容器,确保只判断元素在该容器内的可见性;threshold设置为0.1,意味着元素有10%进入容器可视区域时就会触发回调。 - 状态更新:使用
setArr时通过map创建新数组,遵循React状态不可变的原则,避免直接修改原数组。 - 清理操作:组件卸载时调用
observer.disconnect()停止观察,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Moroshka
相关产品推荐
相关产品推荐

