为何click事件监听器的回调函数会执行两次?
问题原因及解决方案
核心原因
你的.addon元素被嵌套在<label>标签内部,这是触发两次click事件的关键:
- 第一次:点击
.addon时,直接触发你绑定的click监听器,此时内部checkbox的checked状态还未改变,所以输出false。 - 第二次:
<label>有默认行为——点击后会自动触发内部关联的checkbox的点击事件,而这个checkbox的点击事件会通过事件冒泡传递到父元素.addon,再次触发监听器,此时checkbox已经完成状态切换,所以输出true。
本质就是label的默认行为+事件冒泡,导致同一个监听器被连续触发了两次。
可行的解决办法
1. 阻止事件冒泡
在回调函数中阻止事件向上传播,避免checkbox的点击事件触发父元素的监听器:
const toggleAddon = (e, addon) => { e.stopPropagation(); // 阻止事件冒泡 const checkbox = addon.querySelector('input'); console.log(checkbox.checked); checkbox.checked ? addon.classList.remove('selected-plan') : addon.classList.add('selected-plan'); };
2. 直接监听checkbox的change事件
既然逻辑是基于checkbox的状态变化,直接绑定checkbox的change事件更精准,也能从根源避免冒泡问题:
const addons = document.querySelectorAll('.addon'); addons.forEach((addon) => { const checkbox = addon.querySelector('input'); checkbox.addEventListener('change', () => { addon.classList.toggle('selected-plan', !checkbox.checked); }); });
3. 调整HTML结构(移除label包裹)
如果不需要<label>自动触发checkbox的功能,可以把.addon从<label>中移出,或者直接删除<label>标签,彻底避免默认行为的影响。
内容的提问来源于stack exchange,提问作者Sagar Mavai
相关产品推荐
相关产品推荐

