Laravel循环中Bootstrap卡片三点下拉菜单仅首个生效的修复方案
解决Laravel Blade循环中Bootstrap卡片三点菜单仅第一个生效的问题
嘿,这个问题我之前也碰到过!原因很简单——你当前的JavaScript代码只选中了DOM里第一个带有.more类的元素,所以只有第一个卡片的菜单能正常工作,其他卡片的元素根本没被绑定事件。咱们来一步步修改:
问题根源
你的原代码里用了document.querySelector('.more'),这个方法只会返回匹配选择器的第一个DOM元素,后续循环生成的卡片里的.more容器完全没被处理到,自然菜单功能失效。
修复方案
我们需要遍历所有的.more容器,给每个容器单独绑定事件,并且每个容器维护自己的菜单显示状态,不能共用同一个visible变量。
第一步:修正HTML中的重复ID(可选但推荐)
你的Blade循环里给按钮加了id="more-btn",这会导致页面出现多个相同ID的元素,违反HTML规范。建议把这个id去掉,只保留class:
<button class="more-btn"> <span class="more-dot"></span> <span class="more-dot"></span> <span class="more-dot"></span> </button>
第二步:替换JavaScript代码
把原来的JS代码换成下面这段,它会遍历所有卡片的菜单容器,为每个容器单独绑定事件:
// 获取所有的三点菜单容器 const moreContainers = document.querySelectorAll('.more'); moreContainers.forEach(container => { // 每个容器单独获取自己的按钮和菜单 const myBtn = container.querySelector('.more-btn'); const menu = container.querySelector('.more-menu'); let visible = false; // 显示菜单的函数 function showMenu(e) { e.preventDefault(); if (!visible) { visible = true; container.classList.add('show-more-menu'); menu.setAttribute('aria-hidden', false); document.addEventListener('mousedown', hideMenu, false); } } // 隐藏菜单的函数 function hideMenu(e) { // 如果点击的是当前按钮,不执行隐藏 if (myBtn.contains(e.target)) { return; } // 如果菜单是显示状态,执行隐藏 if (visible) { visible = false; container.classList.remove('show-more-menu'); menu.setAttribute('aria-hidden', true); document.removeEventListener('mousedown', hideMenu); } } // 给当前容器的按钮绑定点击事件 myBtn.addEventListener('click', showMenu, false); });
关键改动说明
querySelectorAll替代querySelector:获取页面中所有的.more容器,而不是只拿第一个- forEach遍历每个容器:每个容器内部定义自己的按钮、菜单和
visible状态,避免不同卡片的菜单状态冲突 - 独立的事件处理函数:每个容器的显示/隐藏函数只操作当前容器的DOM元素,不会影响其他卡片的菜单
- 修复重复ID问题:去掉了按钮的重复ID,符合HTML规范,避免潜在的其他DOM操作异常
这样修改后,循环生成的每一个卡片的三点菜单都能正常触发显示和隐藏啦!
内容的提问来源于stack exchange,提问作者Shaan
相关产品推荐
相关产品推荐

