表格中多Bootstrap下拉菜单切换异常:DOM残留及全关问题求助
解决Bootstrap表格中下拉菜单切换异常的问题
问题场景
在<table>中使用Bootstrap下拉菜单时,原本存在菜单被截断、显示异常的问题。将下拉菜单移出表格容器到<body>后,单个下拉菜单点击外部关闭可正常工作,但如果打开一个下拉菜单后立即点击另一行的下拉菜单,会出现所有下拉菜单关闭,且之前打开的菜单DOM残留于<body>中的异常情况。
原HTML代码:
<table> @foreach(...){<tr> <td> <div class="dropdown"> <button data-bs-toggle="dropdown" data-bs-auto-close="true" data-bs-offset="0,2" aria-expanded="false">See review</button> <div class="dropdown-menu" role="menu">/*some menu items*/</div> </div> </td> </tr> } </table>
原JS代码:
var dropdownMenu:any; $('.dropdown').on('show.bs.dropdown', function (e:any) { dropdownMenu = $(this).find('.dropdown-menu'); $('body').append(dropdownMenu.detach()); dropdownMenu.css('display', 'block'); dropdownMenu.position({ 'my': 'right top', 'at': 'right bottom', 'of': $(e.relatedTarget) }); }); $(".dropdown").on('hide.bs.dropdown', function (e: any) { if (dropdownMenu != undefined) { $(e.currentTarget).append(dropdownMenu.detach()); dropdownMenu.hide(); } });
问题原因
- 使用全局变量
dropdownMenu存储当前菜单,切换下拉菜单时,新菜单会覆盖全局变量,导致旧菜单的hide.bs.dropdown事件触发时,无法找到对应的DOM元素,从而残留于<body>中。 - Bootstrap的
data-bs-auto-close="true"会在点击其他下拉按钮时触发所有已打开菜单的隐藏事件,但此时全局变量已指向新菜单,旧菜单无法被正确放回原容器。
修复方案
移除全局变量,改用每个下拉容器的data()方法存储对应菜单;在显示新菜单前主动关闭所有已打开菜单,确保状态一致。
修改后的JS代码:
// 绑定下拉菜单显示事件 $('.dropdown').on('show.bs.dropdown', function (e) { // 先关闭所有已处于打开状态的下拉菜单 $('.dropdown.show').dropdown('hide'); const $currentDropdown = $(this); const $menu = $currentDropdown.find('.dropdown-menu'); // 将当前菜单存入下拉容器的data中,避免全局变量冲突 $currentDropdown.data('attachedMenu', $menu); // 将菜单移到body并设置显示与定位 $('body').append($menu.detach()); $menu.css('display', 'block'); $menu.position({ 'my': 'right top', 'at': 'right bottom', 'of': $(e.relatedTarget) }); }); // 绑定下拉菜单隐藏事件 $(".dropdown").on('hide.bs.dropdown', function () { const $currentDropdown = $(this); // 从当前下拉容器的data中取出对应的菜单 const $menu = $currentDropdown.data('attachedMenu'); if ($menu) { // 将菜单放回原下拉容器并隐藏 $currentDropdown.append($menu.detach()); $menu.hide(); // 清除data中的存储,避免残留 $currentDropdown.removeData('attachedMenu'); } });
关键修改点
- 去掉全局变量,用每个
.dropdown元素的data()存储专属菜单DOM,避免切换时的变量覆盖问题。 - 显示新菜单前主动关闭所有已打开的下拉菜单,触发对应的
hide事件,让旧菜单能正确回到原容器。 - 在
hide事件中从当前下拉容器的data中取菜单,确保操作的是当前容器对应的菜单,不会混淆。
内容的提问来源于stack exchange,提问作者Gyuzal
相关产品推荐
相关产品推荐

