如何在Express+Node.js应用中实现导航汉堡菜单UI切换?
Bulma汉堡菜单在Express项目中失效的解决方案
问题情况
- 原本在CodePen中正常运行的Bulma导航栏汉堡菜单,集成到Express+Node.js项目后无法触发点击事件
- 控制台报错:
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') - 相关代码及项目结构如下:
汉堡菜单JS代码(原)
const burger = document.getElementById('burger'); burger.addEventListener('click', (e) => { console.log('BURGER CLICK'); });
页面布局文件(layout.js)
module.exports = ({ content }) => { return ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>snack attack</title> <link href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet"> <link href="/css/main.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.min.css"></link> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;600&display=swap" rel="stylesheet"> </head> <body> <header> <nav class="navbar has-background-light" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item" href="/"> <h3 class="title">Snack Attack</h3> </a> <a role="button" id="burger" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbar-content"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div id="navbar-content" class="navbar-menu is-centered"> <div class="navbar-start"> <a class="navbar-item"> Home </a> <a class="navbar-item" href="/"> Products </a> </div> <div class="navbar-end"> <div class="navbar-item"> <div class="buttons"> <a href="/cart"> <i class="ri-shopping-bag-line"></i> </a> </div> </div> </div> </div> </nav> </header> ${content} <footer class="footer navbar-top"> <div class="container navbar-container"> <div> <ul class="social"> <li> <a href=""><i class="fa fa-phone"></i>+1 555 987 6543</a> </li> <li> <a href=""><i class="fa fa-envelope"></i> shop@myshop.com</a> </li> </ul> </div> <div> <ul class="social"> <li><a href=""><i class="fab fa-facebook"></i></a></li> <li><a href=""><i class="fab fa-twitter"></i></a></li> </ul> </div> </div> </footer> <script src="navburgerhelper.js"></script> </body> </html> `; };
Express入口文件(index.js)
require('dotenv').config(); const express = require('express'); const bodyParser = require('body-parser'); const mongoose = require('mongoose'); const authRouter = require('./routes/admin/auth'); const productsAdminRouter = require('./routes/admin/products'); const productsRouter = require('./routes/products'); const cartsRouter = require('./routes/carts'); const session = require('express-session'); const app = express(); app.use(express.static('public')); app.use(bodyParser.urlencoded({ extended: true })); app.use(authRouter); app.use(productsAdminRouter); app.use(productsRouter); app.use(cartsRouter); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log('Server listening on http://localhost:' + PORT); });
原项目结构
app/views/layout.js app/navburgerhelper.js app/index.js
问题原因
- 静态文件访问权限:Express仅将
public/目录设置为静态资源目录,app/下的navburgerhelper.js无法被前端直接请求,导致JS文件未加载,获取DOM元素时返回null - 缺少DOM加载判断:即使文件路径正确,若DOM未完全加载就执行JS,也可能导致获取不到元素
解决步骤
1. 调整JS文件位置
将navburgerhelper.js移动到public/目录下,调整后项目结构:
app/views/layout.js app/public/navburgerhelper.js app/index.js
2. 修正script标签路径
在layout.js中修改script的src属性,确保指向正确的静态资源路径:
<script src="/navburgerhelper.js"></script>
3. 完善汉堡菜单切换逻辑
更新navburgerhelper.js代码,添加DOM加载判断和Bulma要求的类名切换逻辑:
// 等待DOM完全加载后执行 document.addEventListener('DOMContentLoaded', () => { const burger = document.getElementById('burger'); const menu = document.getElementById('navbar-content'); // 确保元素存在再绑定事件 if (burger && menu) { burger.addEventListener('click', () => { // 切换汉堡按钮的激活状态 burger.classList.toggle('is-active'); // 切换导航菜单的显示状态 menu.classList.toggle('is-active'); }); } });
4. 确保Express静态资源配置正确
如果public目录不在项目根目录(比如在app/下),需要调整index.js中的静态资源配置,先引入path模块:
const path = require('path');
然后修改静态资源配置:
app.use(express.static(path.join(__dirname, 'public')));
验证
重启Express服务器,刷新页面后点击汉堡菜单,导航栏应能正常展开/收起,控制台无报错。
内容的提问来源于stack exchange,提问作者rachel
相关产品推荐
相关产品推荐

