Next.js 多路由下Header滚动切换背景色的逻辑优化
Header样式逻辑调整方案
- 先修复原有代码的基础bug:
- 事件监听器配对错误:原代码挂载时给窗口绑定了
scroll滚动监听事件,组件卸载时却尝试移除从未绑定过的resize事件监听,会导致组件卸载后滚动逻辑仍持续运行,造成内存泄漏 - 缺少路由判断分支:原滚动逻辑只判断滚动到顶部的条件,不区分当前处于哪个路由,导致非首页路由滚动到顶部时,错误给Header加上了蓝底白字的测试类
- 零散操作DOM类的写法耦合度高,路由切换时之前加在Header、导航上的类不会自动清除,容易出现跨页面的样式污染
- 事件监听器配对错误:原代码挂载时给窗口绑定了
- 核心逻辑调整思路:
- 不再单独在滚动监听、路由初始化时零散操作DOM类,直接把「是否加载自定义Header样式」的判断和「当前路由」「页面滚动位置」两个强绑定条件挂钩,两个条件同时满足才给元素加对应类
- 用React状态记录页面是否在顶部位置,替代手动操作DOM类的写法,路由切换、状态更新时样式会自动跟随渲染,不会出现旧类残留的问题
- 修正原来监听器配对错误的问题,避免组件卸载后滚动逻辑还在运行
修正后的完整组件代码
import { useEffect, useState } from "react"; import Link from "next/link"; import styles from "./header.module.css"; import { useRouter } from "next/router"; export default function Header() { const router = useRouter(); // 记录当前页面是否处于顶部位置 const [isPageTop, setIsPageTop] = useState(true); const handleClick = (path) => { if (path === "/mvg") { console.log("I clicked on the mvg Page"); } }; // 监听页面滚动,更新顶部位置状态 useEffect(() => { const checkScrollPosition = () => { setIsPageTop(window.scrollY === 0); }; // 初始加载时先校验一次当前滚动位置 checkScrollPosition(); window.addEventListener("scroll", checkScrollPosition); // 组件卸载时移除对应监听器,避免内存泄漏 return () => window.removeEventListener("scroll", checkScrollPosition); }, []); // 计算最终需要加载的自定义样式类:只有首页+页面在顶部时才生效 const isTransparentStyle = router.pathname === "/" && isPageTop; return ( <header className={`${styles.header} ${isTransparentStyle ? "headerTest" : ""}`} > <h1> <Link href="/"> <a> <span className="offscreen">Home</span> </a> </Link> </h1> <nav id="menu" className={`${styles.menu} ${isTransparentStyle ? "menuTest" : ""}`} > <ul> <li> <Link href="/mvg"> <a onClick={() => handleClick("/mvg")}>MVG</a> </Link> </li> </ul> </nav> </header> ); }
逻辑生效规则说明
调整后的逻辑完全匹配预期交互:
- 首页场景下:页面在顶部时加载蓝底白字自定义样式,向下滚动时自动切换为白底默认样式,回滚到顶部时再次恢复自定义样式
/mvg等非首页路由下:无论页面滚动到什么位置(包括刚加载、滚动到顶部),都不会加载自定义样式,始终保持白底默认效果- 原有移动端宽度限制的逻辑可以直接合并到自定义样式的判断条件中,比如补充判断
window.innerWidth > 768,不需要单独操作DOM类
内容的提问来源于stack exchange,提问作者dev_el
相关产品推荐
相关产品推荐

