ReactJS如何通过onScroll方法实现页面滚动时修改组件状态
问题根源
原有代码不生效核心原因如下:
- 你将
onScroll事件绑定在了普通div元素上,该元素没有设置固定高度与滚动溢出属性,自身不会产生滚动事件,回调永远不会触发 - 页面级的滚动事件是挂载在
window对象上的,无法通过普通元素的onScroll属性直接捕获 - 缺少事件监听的清理逻辑,组件卸载后残留监听会引发内存泄漏
可用实现方案
通过useEffect在组件挂载时绑定window的全局滚动监听,组件卸载时自动移除监听,替换原有Header组件代码即可:
import { useState, useEffect } from 'react'; const Header = () => { const [background, setBackground] = useState(false); // 滚动事件处理逻辑 const handleScroll = () => { // 若需要滚动后永久保留背景,直接写 setBackground(true) 即可 // 下面写法支持滚动回顶部时恢复无背景状态,体验更好 setBackground(window.scrollY > 0); }; useEffect(() => { // 绑定全局滚动监听 window.addEventListener('scroll', handleScroll); // 组件卸载时移除监听,避免内存泄漏 return () => window.removeEventListener('scroll', handleScroll); }, []); return ( <div> <div> {/* 提示:如果需要导航固定在顶部始终可见,给className追加 fixed top-0 left-0 z-50 即可 */} <div className={background ? 'nav bg-error w-[90%] py-5 mx-auto text-[white] flex justify-between ' : 'nav w-[90%] py-5 mx-auto text-[white] flex justify-between'}> <div> <p> logo</p> </div> <div> <ul className='flex justify-around'> <li>item1</li> <li className='mx-10'>item2</li> <li className='mr-10'>item3</li> <li>item4</li> </ul> </div> </div> </div> <div className=' text-[white]'> <img src="https://img.freepik.com/free-photo/close-up-islamic-new-year-concept_23-2148611670.jpg?w=1380&t=st=1655822165~exp=1655822765~hmac=c5954765a3375adc1b56f2896de7ea8a604cd1fb725e53770c7ecd8a05821a60" alt="banner" /> </div> </div> ); }; export default Header;
可选优化
如果页面滚动场景复杂,可以给handleScroll增加节流逻辑,控制事件触发频率在每16ms一次(匹配普通屏幕刷新率),避免频繁触发状态更新造成性能损耗。
内容的提问来源于stack exchange,提问作者Md Joynul Abedin
相关产品推荐
相关产品推荐

