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

React项目中正确导入Nav.js脚本的问题求助

问题分析与解决方案

你的核心问题是原生DOM操作脚本与React的组件渲染机制不兼容。直接导入或加载原生Nav.js时,脚本会在React组件渲染出对应DOM元素前执行,导致找不到节点抛出错误,刷新后页面空白;汉堡菜单无响应则是因为事件绑定时机不对,或路由切换后DOM重新生成但事件未重新绑定。

下面是两种可行的解决思路:


方案一:改用React组件化写法(推荐)

废弃原生Nav.js,将导航逻辑直接集成到Header组件中,用React的状态管理替代DOM操作:

// components/Header.jsx
import { useState } from 'react';

const Header = () => {
  // 用状态控制导航栏的激活状态
  const [isNavActive, setIsNavActive] = useState(false);

  const toggleNavbar = () => {
    setIsNavActive(prev => !prev);
  };

  const closeNavbar = () => {
    setIsNavActive(false);
  };

  return (
    <header className="header">
      {/* 导航容器:根据状态添加active类 */}
      <nav data-navbar className={isNavActive ? 'active' : ''}>
        <a href="/" data-nav-link onClick={closeNavbar}>首页</a>
        <a href="/about" data-nav-link onClick={closeNavbar}>关于</a>
        <a href="/create" data-nav-link onClick={closeNavbar}>写博客</a>
        {/* 其他导航链接 */}
      </nav>
      {/* 汉堡按钮:根据状态添加active类 */}
      <button 
        data-nav-toggler 
        className={isNavActive ? 'active' : ''} 
        onClick={toggleNavbar}
      >
        {/* 汉堡图标(保留原模板的HTML结构即可) */}
        <span></span>
        <span></span>
        <span></span>
      </button>
    </header>
  );
};

export default Header;

修改App.js,移除无用的Helmet脚本导入:

// App.js
import './app.css';
import Home from './pages/Home';
import { Routes, Route } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import Detail from './pages/Detail';
import AddEditBlog from "./pages/AddEditBlog";
import About from "./pages/About";
import NotFound from "./pages/NotFound";
import Header from './components/Header';

function App() {
  return (
    <div className='app'>
      <Header/>
      <Routes>
        <Route path="/" element={<Home/>}/>
        <Route path="/detail/:id" element={<Detail />}/>
        <Route path="/create" element={<AddEditBlog />}/>
        <Route path="/update/:id" element={<AddEditBlog />}/>
        <Route path="/about" element={<About />}/>
        <Route path="*" element={<NotFound/>}/>
      </Routes>
      <ToastContainer />
    </div>
  );
}

export default App;

方案二:保留原生脚本,通过useEffect绑定事件

如果不想完全重写原生逻辑,可在Header组件中用useEffect确保DOM渲染完成后再执行脚本,并添加清理函数避免内存泄漏:

// components/Header.jsx
import { useEffect } from 'react';

const Header = () => {
  useEffect(() => {
    // 复制原Nav.js的逻辑
    const addEventOnElem = function (elem, type, callback){
      if(elem.length>1){
        for(let i = 0;i<elem.length;i++){
          elem[i].addEventListener(type, callback);
        }
      }else{
        elem.addEventListener(type,callback);
      }
    }

    const navbar = document.querySelector("[data-navbar]");
    const navbarLinks = document.querySelectorAll("[data-nav-link]")
    const navToggler = document.querySelector("[data-nav-toggler]");

    const toggleNavbar = function(){
      navbar.classList.toggle("active");
      this.classList.toggle("active");
    }
    addEventOnElem(navToggler, "click", toggleNavbar);

    const closeNavbar = function(){
      navbar.classList.remove("active");
      navToggler.classList.remove("active");
    }
    addEventOnElem(navbarLinks, "click", closeNavbar);

    // 组件卸载时移除事件监听,避免内存泄漏
    return () => {
      addEventOnElem(navToggler, "click", toggleNavbar);
      addEventOnElem(navbarLinks, "click", closeNavbar);
    };
  }, []); // 空依赖数组确保只执行一次

  // 保留原Header的HTML结构
  return (
    <header className="header">
      <nav data-navbar>
        {/* 导航链接 */}
      </nav>
      <button data-nav-toggler>
        {/* 汉堡图标 */}
      </button>
    </header>
  );
};

export default Header;

为什么原来的方法无效?

  1. Helmet/HTML中直接加载脚本:脚本会在React组件渲染出DOM前执行,document.querySelector找不到[data-navbar]等元素,抛出错误导致页面空白。
  2. 路由切换后无响应:路由切换时Header组件会重新渲染,生成新的DOM元素,但原生脚本只在页面加载时绑定一次事件,新元素没有事件监听,所以汉堡菜单点击无效。

内容的提问来源于stack exchange,提问作者Hans Kristian Kristoffersen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 17:25:26