Rails 7 + Turbo环境下子菜单点击链接时闪烁问题求助
问题:Rails 7 + Turbo 下子菜单点击链接时其他子菜单闪烁的解决办法
我基于 Rails 7、Bootstrap 5 和 jQuery 实现了一个可切换的子菜单:点击按钮展开对应子菜单,同时自动收起其他子菜单。但测试时发现,点击子菜单内的链接(控制器加了3秒延迟模拟慢加载),其他子菜单会出现持续3秒的闪烁,禁用 Turbo 后问题消失。
原实现代码
HTML
<div> <button class="toggle-submenu">Sales</button> <div class="submenu"> <ul> <li><a href="/sales/recent">Recent</a></li> <li><a href="/sales">All</a></li> </ul> </div> </div> <div> <button class="toggle-submenu">Products</button> <div class="submenu"> <ul> <li><a href="/products">All</a></li> </ul> </div> </div>
CSS
.submenu { height: 0; overflow: hidden; } .submenu-open { height: auto; }
JavaScript
$(document).on('click', '.toggle-submenu', function() { $(this).parent().find('.submenu').toggleClass('submenu-open'); $('.submenu').not($(this).parent().find('.submenu')).removeClass('submenu-open'); });
解决方案
问题根源在于 Turbo 在导航过程中会保留/修改 DOM 状态,导致菜单的显示逻辑出现异常,以下是几种可行的解决方式:
1. 导航前重置菜单状态
监听 Turbo 的请求发起事件,在页面开始加载前主动收起所有子菜单,避免状态混乱:
$(document).on('turbo:before-fetch-request', function() { $('.submenu').removeClass('submenu-open'); });
2. 标记菜单为永久保留元素
给菜单的外层容器添加 data-turbo-permanent 属性,让 Turbo 在页面置换时保留该容器及其状态,不会重新渲染菜单部分:
<div data-turbo-permanent> <div> <button class="toggle-submenu">Sales</button> <div class="submenu">...</div> </div> <div> <button class="toggle-submenu">Products</button> <div class="submenu">...</div> </div> </div>
3. 优化事件绑定逻辑
将菜单的点击事件绑定放在 Turbo 的页面加载事件中,确保每次页面置换后事件都能正确绑定,避免旧事件残留导致的异常:
$(document).on('turbo:load', function() { // 先移除旧绑定,避免重复触发 $('.toggle-submenu').off('click'); $('.toggle-submenu').on('click', function() { const targetSubmenu = $(this).parent().find('.submenu'); targetSubmenu.toggleClass('submenu-open'); $('.submenu').not(targetSubmenu).removeClass('submenu-open'); }); });
内容的提问来源于stack exchange,提问作者almo
相关产品推荐
相关产品推荐

