Next+TypeScript项目如何检测元素进出视口修改导航栏样式
实现方案(推荐:无需jQuery,完美适配Next.js + TypeScript)
报错原因说明
你遇到的window is undefined报错是因为Next.js默认开启服务端预渲染,服务端运行环境不存在window、document等浏览器专属API,直接引入jQuery或者在组件顶层操作浏览器API都会触发该错误。使用React原生Hook实现不需要引入额外依赖,也能完全规避TS兼容问题。
完整实现代码
import { NextPage } from 'next'; import { useState, useEffect, useRef } from 'react'; // 引入样式文件,也可以用CSS-in-JS方案 import styles from './Home.module.css'; const Home: NextPage = () => { // 存储导航是否滚动到目标位置的状态 const [isNavActive, setIsNavActive] = useState(false); // 绑定目标div的ref,用于获取位置信息 const targetDivRef = useRef<HTMLDivElement>(null); useEffect(() => { // 仅在客户端环境执行 if (typeof window === 'undefined') return; const handleScroll = () => { if (!targetDivRef.current) return; // 获取目标div距离页面顶部的高度 const targetTop = targetDivRef.current.offsetTop; // 获取当前页面滚动距离 const scrollTop = window.scrollY; // 滚动位置超过目标div顶部时修改状态 setIsNavActive(scrollTop >= targetTop); }; // 绑定滚动监听事件 window.addEventListener('scroll', handleScroll); // 组件卸载时解绑事件,避免内存泄漏 return () => window.removeEventListener('scroll', handleScroll); }, []); return ( <> {/* 动态绑定样式类 */} <nav className={`${styles.nav} ${isNavActive ? styles.navActive : ''}`}> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> </ul> </nav> <main> <div id="firstDiv"> {/* more code */} </div> {/* 给目标div绑定ref */} <div id="divToHideNav" ref={targetDivRef}> {/* more code */} </div> </main> </> ); }; export default Home;
样式示例(Home.module.css)
.nav { position: fixed; top: 0; width: 100%; padding: 20px; background: transparent; transition: all 0.3s ease; z-index: 999; } .navActive { background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,0.1); color: #000; }
可选:jQuery兼容实现方案
如果必须使用jQuery,需要确保仅在客户端动态引入,避免服务端预渲染阶段执行:
useEffect(() => { if (typeof window === 'undefined') return; // 动态引入jQuery import('jquery').then($ => { const handleScroll = () => { const targetTop = $('#divToHideNav').offset()?.top || 0; if ($(window).scrollTop() >= targetTop) { $('#myNav').addClass('active'); } else { $('#myNav').removeClass('active'); } }; $(window).on('scroll', handleScroll); return () => $(window).off('scroll', handleScroll); }); }, []);
注意:该方案需要先安装jQuery和对应的TS类型依赖:
npm i jquery @types/jquery
内容的提问来源于stack exchange,提问作者Gustavo Farias
相关产品推荐
相关产品推荐

