如何在事件冒泡场景下禁用被点击的LI子元素点击监听?
解决方案:点击后禁用单个li的交互(基于事件冒泡)
这问题刚好能利用事件委托的特性优雅解决,核心思路是在ul的点击事件处理器里精准定位被点击的li,给它标记“已点击”状态,后续点击时直接跳过处理就行。我给你两种实用的实现方式:
方法1:用CSS类禁用点击(推荐,兼顾交互与视觉反馈)
这种方式通过添加自定义类,同时实现交互禁用和视觉状态改变,代码清晰好维护。
首先添加CSS样式:
/* 禁用点击的样式,同时添加视觉标记 */ .disabled-star { pointer-events: none; opacity: 0.5; color: #ccc; }
然后完善你的JavaScript代码:
const ulDeck = document.querySelector(".stars"); // 动态创建16个li元素(补全你的创建逻辑) for (let i = 0; i < 16; i++) { const li = document.createElement("li"); const starIcon = document.createElement("i"); starIcon.className = "fa fa-star"; li.appendChild(starIcon); ulDeck.appendChild(li); } // 绑定事件委托 ulDeck.addEventListener('click', showStar, false); function showStar(e) { // 兼容点击到li内部的i标签,找到最近的li元素 const clickedLi = e.target.closest('li'); // 如果不是li元素,或者已经被禁用,直接返回 if (!clickedLi || clickedLi.classList.contains('disabled-star')) { return; } // 这里写你的点击业务逻辑,比如触发动画、记录数据等 console.log(`第${Array.from(ulDeck.children).indexOf(clickedLi)+1}个星星被点击`); // 给当前li添加禁用类,阻止后续点击 clickedLi.classList.add('disabled-star'); }
方法2:用自定义数据属性标记(纯JS控制,无额外CSS)
如果不需要额外的视觉样式,或者想完全用JS控制状态,可以用HTML5的自定义数据属性来标记已点击的li:
const ulDeck = document.querySelector(".stars"); // 动态创建16个li元素 for (let i = 0; i < 16; i++) { const li = document.createElement("li"); const starIcon = document.createElement("i"); starIcon.className = "fa fa-star"; li.appendChild(starIcon); ulDeck.appendChild(li); } ulDeck.addEventListener('click', showStar, false); function showStar(e) { const clickedLi = e.target.closest('li'); // 如果不是li,或者已经被标记为已点击,直接返回 if (!clickedLi || clickedLi.dataset.clicked === 'true') { return; } // 你的业务逻辑 console.log('星星被点击'); // 标记为已点击,后续点击不再响应 clickedLi.dataset.clicked = 'true'; // 可选:手动添加视觉变化 clickedLi.style.opacity = '0.5'; }
关键细节说明:
- 用
e.target.closest('li')而不是直接判断e.target,是因为用户可能点击到li内部的<i>标签,这样能确保我们总能找到对应的li元素。 - 事件委托的优势在这里体现得淋漓尽致:不需要给每个li单独绑定事件,只需要在父元素ul上绑定一次,动态创建的li也能自动响应。
内容的提问来源于stack exchange,提问作者Tim Schneider
相关产品推荐
相关产品推荐

