Next.js 13滚动事件监听器未触发问题求助
滚动事件监听器未生效的原因排查(Next.js 13 + Tailwind CSS)
问题根源
你的代码存在两个核心问题导致滚动事件监听器未生效:
事件监听器注册位置错误
你将window.addEventListener("scroll", handleShadow, true);写在了handleShadow函数内部,这意味着只有当handleShadow被调用时才会注册监听器,但初始渲染时这个函数从未被执行,所以监听器根本没被添加到window上。移除监听器的参数不匹配
虽然你返回了移除监听器的函数,但如果监听器未被正确注册,移除操作毫无意义;另外,添加监听器时使用了第三个参数true(捕获阶段),移除时却没带上该参数,即使后续监听器被注册,也可能无法正确移除。
修正后的代码
状态与事件监听部分
const [shadow, setShadow] = useState(false); useEffect(() => { const handleShadow = () => { // 简化状态更新逻辑 setShadow(window.scrollY >= 90); }; // 在useEffect初始化时直接注册滚动事件 window.addEventListener("scroll", handleShadow, true); // 移除监听器时保持参数与添加时完全一致 return () => { window.removeEventListener("scroll", handleShadow, true); }; }, []);
导航栏组件部分
可以用模板字符串简化className的条件判断,减少重复代码:
<div className={`fixed left-0 top-0 w-full z-10 ease-in duration-300 bg-[#112240] ${shadow ? 'shadow-xl' : ''}`}> {/* 其他导航栏内容 */} </div>
关键修正说明
- 将事件监听器的注册逻辑移到
handleShadow函数外部,确保组件挂载时就完成监听器注册 - 简化状态更新语句,直接用滚动位置的判断结果赋值给状态
- 移除监听器时严格匹配添加时的所有参数,避免内存泄漏
- 优化className的写法,利用Tailwind的类名组合特性减少冗余
内容的提问来源于stack exchange,提问作者kryptonian
相关产品推荐
相关产品推荐

