Ruby on Rails页面切换后响应式导航栏汉堡菜单功能失效问题
问题根因
你当前使用的是Rails框架默认集成的Turbo(旧版本称为TurboLinks),页面跳转时不会触发完整的页面重载,你代码中监听的DOMContentLoaded事件仅在首次进入站点时执行一次。跳转后导航栏DOM元素会被新内容替换,之前绑定在旧.burger-menu元素上的点击事件随着旧DOM被销毁而失效,新渲染的汉堡按钮没有绑定对应点击事件,所以点击无响应。
解决方案
推荐使用事件委托的方式绑定事件,不需要依赖页面加载事件,也不会出现重复绑定的问题:
// 把事件绑定在document上,点击时自动判断触发源是否为汉堡按钮 document.addEventListener('click', (e) => { const burgerBtn = e.target.closest('.burger-menu') if (!burgerBtn) return const responsiveMenu = document.querySelector('.responsive-navbar'); const body = document.querySelector('body'); const responsiveLinks = document.querySelectorAll('.responsive-menu-links') burgerBtn.classList.toggle('cross') responsiveMenu.classList.toggle('menu-open'); body.classList.toggle('disable-scroll'); responsiveLinks.forEach(link => { link.classList.toggle('trigger-anim') }) })
如果你不想修改原有事件绑定逻辑,也可以将原来的DOMContentLoaded事件替换为Turbo的专属加载事件,注意要提前移除旧事件避免重复绑定:
// 提前抽离事件处理函数 function bindBurgerMenu() { let responsiveMenu = document.querySelector('.responsive-navbar'); let body = document.querySelector('body'); let burgerBtn = document.querySelector('.burger-menu'); // 先移除旧监听器,避免跳转后重复绑定 burgerBtn.removeEventListener('click', handleBurgerClick) burgerBtn.addEventListener('click', handleBurgerClick) } function handleBurgerClick() { const burgerBtn = document.querySelector('.burger-menu') const responsiveMenu = document.querySelector('.responsive-navbar'); const body = document.querySelector('body'); const responsiveLinks = document.querySelectorAll('.responsive-menu-links') burgerBtn.classList.toggle('cross') responsiveMenu.classList.toggle('menu-open'); body.classList.toggle('disable-scroll'); responsiveLinks.forEach(link => { link.classList.toggle('trigger-anim') }) } // 监听Turbo页面加载完成事件 document.addEventListener('turbo:load', bindBurgerMenu) // 如果你用的是旧版Rails的TurboLinks,替换为监听 turbolinks:load 事件即可
额外优化建议
菜单打开状态下跳转页面时,body的disable-scroll类可能残留导致新页面无法滚动,可以监听Turbo跳转前事件清理菜单状态:
document.addEventListener('turbo:before-visit', () => { const burgerBtn = document.querySelector('.burger-menu') const responsiveMenu = document.querySelector('.responsive-navbar'); const body = document.querySelector('body'); const responsiveLinks = document.querySelectorAll('.responsive-menu-links') burgerBtn?.classList.remove('cross') responsiveMenu?.classList.remove('menu-open'); body?.classList.remove('disable-scroll'); responsiveLinks?.forEach(link => link.classList.remove('trigger-anim')) })
内容的提问来源于stack exchange,提问作者Ale Yanczuk
相关产品推荐
相关产品推荐

