为何冒泡阶段调用preventDefault()会阻止checkbox的默认勾选状态切换?
Checkbox点击无法切换勾选状态的原因及解决办法
问题场景
给包含checkbox的.container元素绑定了冒泡阶段的click事件监听器,监听器内调用e.preventDefault()。点击checkbox时,发现其勾选状态无法切换,原本以为checkbox的勾选操作会在事件冒泡到container之前完成,调用preventDefault()不会影响它,对此产生困惑。
代码示例
HTML
<div class="container"> <input type="checkbox"> </div>
CSS
.container{ padding:2rem; background-color: blue; }
JavaScript
document.querySelector(".container").addEventListener("click" , function(e){ e.preventDefault() })
原因分析
核心逻辑很简单:checkbox的勾选切换属于click事件的默认行为,而这个默认行为的执行时机是在整个事件流(捕获+冒泡阶段所有事件处理函数全部执行完毕)之后。
你在container的冒泡阶段调用e.preventDefault(),相当于阻止了整个click事件的所有默认行为——哪怕这个行为是属于子元素checkbox的。因为事件流是从目标元素(checkbox)往外冒泡,所有父元素的事件处理函数都执行完,才会触发默认行为,这时候只要任何一个事件处理函数调用了preventDefault(),都会把整个默认行为拦下来。
解决办法
有两种简单的处理方式:
- 阻止checkbox的事件冒泡:给checkbox单独绑定click事件,调用
e.stopPropagation(),让事件不会冒泡到container,这样container的preventDefault()就不会影响它的勾选:document.querySelector(".container input[type='checkbox']").addEventListener("click", function(e){ e.stopPropagation() }) - 在container的事件中判断目标元素:如果点击的是checkbox,就不执行
preventDefault():document.querySelector(".container").addEventListener("click", function(e){ if(!(e.target instanceof HTMLInputElement && e.target.type === 'checkbox')){ e.preventDefault() } })
内容的提问来源于stack exchange,提问作者thefreedevil1995
相关产品推荐
相关产品推荐

