You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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;

关键修改说明

  1. CSS Modules类名的正确用法
    所有类名都必须通过styles.xxx调用,比如styles.showNav,这是CSS Modules的核心特性——局部作用域类名,既避免了全局样式污染,又能确保你操作的是实际渲染到页面上的类名。

  2. 用useRef获取DOM元素
    React中不推荐直接使用document.querySelector,因为组件渲染周期内DOM可能未就绪(这也是你之前不用useEffect就报错的原因),useRef可以安全、可靠地获取到DOM元素的引用。

  3. 修复事件监听逻辑

    • 你之前在forEach里刚添加菜单链接的点击事件就立刻移除,导致菜单点击完全无效,现在把移除操作放在useEffect的清理函数中,组件卸载时再统一移除,保证事件正常生效。
    • 给useEffect添加空依赖数组,确保事件仅在组件挂载时绑定一次,避免重复绑定引发的异常。
  4. 移除多余全局类名
    比如ham、navbar这类全局类名完全不需要,CSS Modules已经通过styles.xxx提供了唯一的类名标识。

你的_nav_module.scss文件无需修改,保持原样即可。

内容的提问来源于stack exchange,提问作者elmaci

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 04:54:08