为什么在父元素上使用preventDefault()点击'禁用'一个复选框?

pet*_*ter 9 html javascript checkbox preventdefault stoppropagation

我最近遇到过这种情况(这里简化).只需用一个元素包装一个复选框,并在它的click事件上应用preventDefault(),然后该复选框将被取消选中.

看到这个小提琴,但这里是一个剪辑:

<div>
    <input type="checkbox"/>
</div> 

/* Wrapper could be any element (and any ancestor element will work) */
$('div').on('click', function(e){
    e.preventDefault();
});


/* Uncomment to make the checkbox work again 
$('input').on('click', function(e){
    e.stopPropagation();
});
*/
Run Code Online (Sandbox Code Playgroud)

行为发生在Chrome和FF中,所以我认为这是有意的.

为什么已经在复选框上触发的click事件不会导致复选框被切换?在preventDefault对祖先好像它应该是风马牛不相及的孩子复选框的行为.似乎,为了发生复选框更改,click事件需要一直自由地冒泡到文档根目录.

这里发生了什么?

Ber*_*rgi 12

对祖先的preventDefault似乎应该与子复选框的行为无关.

不,不是真的.事件起泡,所有处理程序(包括祖先的处理程序)都可能影响它.

似乎,为了发生复选框更改,click事件需要一直自由地冒泡到文档根目录.

不完全是.它不需要到达文档根目录,但它不能被默认阻止.

您可能希望阅读DOM规范中有关事件流,默认操作和可取消事件的体系结构说明.

那么一步一步发生什么呢?

  1. 您单击复选框
  2. 它被检查
  3. 该事件将在文档根目录上分派
  4. (不在IE中):捕获阶段,处理程序没有任何反应
  5. 活动到达了 <input>
  6. ......并开始冒泡
  7. <div>,它被处理.您的事件侦听器调用该preventDefault方法,设置内部cancelled标志.
  8. 泡泡,但没有任何事情发生.
  9. 由于事件已取消,因此不应执行默认操作,并将复选框重置为其先前状态.

如果取消注释代码的第二部分,则步骤6+看起来不同:

  1. 该事件是在<input>.您的侦听器调用该stopPropagation方法
  2. ...导致跳过冒泡阶段.(永远不会调用div-listener)
  3. 未阻止默认操作,并且复选框保持选中状态.


Dav*_*und 5

preventDefault防止触发浏览器的默认操作.更改复选框的选中状态或跟随href锚点,提交表单等是默认操作.preventDefault在允许事件传播的同时阻止它们.

这与事件传播不同(您可以 - 正如您所指出的那样 - 停止stopPropagation).在调用浏览器的默认行为之前,事件将在整个侦听器层次结构中传播(除非被阻止).

  • 简洁的答案."preventDefault"和"stopPropagation"的确切目的需要在我脑海中澄清 - 我一直把它们粗暴地看作是"当你遇到祖先/后代问题时要尝试的事情".非常感谢! (2认同)