在useEffect钩子中通过addEventListener更新类名:汉堡菜单按钮点击样式不生效问题排查
我一眼就看出问题所在了——你在用CSS Modules,但操作类名的方式完全错了!CSS Modules会把你的类名编译成唯一的哈希值(比如_nav_module__navbar_xyz),你直接用.navbar或者showNav这种字符串类名,根本匹配不上实际渲染的类名,这就是点击没反应的核心原因。另外还有几个小问题也得一起修正,我给你整理好完整的解决方案:
修正后的Nav.js代码
import { useEffect, useRef } from 'react'; import styles from './_nav_module.scss'; // 确保导入路径与你的文件位置一致 const Nav = () => { // 用useRef安全获取DOM元素,替代原生querySelector const navbarRef = useRef(null); const hamRef = useRef(null); const menuLinkRefs = useRef([]); const toggleHamburger = () => { // 直接使用styles对象中的类名,这是CSS Modules编译后的正确类名 navbarRef.current.classList.toggle(styles.showNav); hamRef.current.classList.toggle(styles.showClose); }; useEffect(() => { const ham = hamRef.current; const menuLinks = menuLinkRefs.current; // 绑定汉堡按钮点击事件 ham.addEventListener('click', toggleHamburger); // 给所有菜单链接绑定点击事件 menuLinks.forEach(link => { link.addEventListener('click', toggleHamburger); }); // 清理函数:组件卸载时移除所有事件监听,避免内存泄漏 return () => { ham.removeEventListener('click', toggleHamburger); menuLinks.forEach(link => { link.removeEventListener('click', toggleHamburger); }); }; }, []); // 空依赖数组确保仅在组件挂载时执行一次 return ( <div> {/* 直接使用styles中的类名,无需额外全局类名 */} <button ref={hamRef} className={styles.ham}></button> <nav ref={navbarRef} className={styles.navbar}> <ul> {/* 用ref数组收集所有菜单链接的DOM元素 */} <li><a ref={el => menuLinkRefs.current.push(el)} className={styles.menuLink} href="#">Home</a></li> <li><a ref={el => menuLinkRefs.current.push(el)} className={styles.menuLink} href="#">Profile</a></li> <li><a ref={el => menuLinkRefs.current.push(el)} className={styles.menuLink} href="#">About</a></li> <li><a ref={el => menuLinkRefs.current.push(el)} className={styles.menuLink} href="#">Contacts</a></li> </ul> </nav> </div> ); }; export default Nav;
关键修改说明
CSS Modules类名的正确用法
所有类名都必须通过styles.xxx调用,比如styles.showNav,这是CSS Modules的核心特性——局部作用域类名,既避免了全局样式污染,又能确保你操作的是实际渲染到页面上的类名。用useRef获取DOM元素
React中不推荐直接使用document.querySelector,因为组件渲染周期内DOM可能未就绪(这也是你之前不用useEffect就报错的原因),useRef可以安全、可靠地获取到DOM元素的引用。修复事件监听逻辑
- 你之前在forEach里刚添加菜单链接的点击事件就立刻移除,导致菜单点击完全无效,现在把移除操作放在useEffect的清理函数中,组件卸载时再统一移除,保证事件正常生效。
- 给useEffect添加空依赖数组,确保事件仅在组件挂载时绑定一次,避免重复绑定引发的异常。
移除多余全局类名
比如ham、navbar这类全局类名完全不需要,CSS Modules已经通过styles.xxx提供了唯一的类名标识。
你的_nav_module.scss文件无需修改,保持原样即可。
内容的提问来源于stack exchange,提问作者elmaci
相关产品推荐
相关产品推荐

