为什么在父元素上单击“禁用"复选框会使用 preventDefault()? [英] Why does preventDefault() on a parent element's click 'disable' a checkbox?

查看:19
本文介绍了为什么在父元素上单击“禁用"复选框会使用 preventDefault()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近遇到了这种情况(这里简化了).简单地用一个元素包裹一个复选框,并在它的点击事件上应用 preventDefault() ,复选框变得不可选中.

参见这个小提琴,但这里有一个片段:

<input type="checkbox"/>

/* 包装器可以是任何元素(任何祖先元素都可以工作)*/$('div').on('click', function(e){e.preventDefault();});/* 取消注释以使复选框再次工作$('input').on('click', function(e){e.stopPropagation();});*/

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

为什么已经在复选框本身上触发的点击事件不会导致复选框被切换?祖先上的 preventDefault 似乎应该与子复选框的行为无关.似乎要发生复选框更改,单击事件需要一直自由冒泡到文档根目录.

这是怎么回事?

解决方案

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

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

<块引用>

似乎要使复选框发生更改,单击事件需要一直自由冒泡到文档根目录.

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

您可能想阅读 事件流默认操作和可取消事件.

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

  1. 您点击复选框
  2. 它被检查
  3. 在文档根目录上调度事件
  4. (不在 IE 中):捕获阶段,您的处理程序没有任何反应
  5. 事件到达
  6. ……然后开始冒泡
  7. 上进行处理.您的事件侦听器调用 preventDefault 方法,设置内部 cancelled 标志.
  8. 它继续冒泡,但没有任何反应.
  9. 由于事件已取消,因此不应发生默认操作,并且复选框将重置为之前的状态.

如果您取消注释第二部分代码,步骤 6+ 看起来会有所不同:

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

I encountered this situation recently (simplified here). Simply wrap a checkbox with an element and apply preventDefault() on it's click event and the checkbox becomes uncheckable.

See this fiddle, but here's a snip:

<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();
});
*/

The behavior occurs in Chrome and FF, so I assume it is intentional.

Why does the click event, which has already been triggered on the checkbox itself not result in the checkbox getting toggled? The preventDefault on the ancestor seems like it ought to be irrelevant to the child checkbox's behavior. It seems as if, for the checkbox change to occur, the click event needs to bubble freely all the way to the document root.

What's going on here?

解决方案

The preventDefault on the ancestor seems like it ought to be irrelevant to the child checkbox's behavior.

No, not really. The event bubbles, and all handlers (including the ones on ancestors) may affect it.

It seems as if, for the checkbox change to occur, the click event needs to bubble freely all the way to the document root.

Not exactly. It doesn't need to arrive at the document root, but it must not have been default-prevented.

You might want to read the architecture notes in the DOM spec on event flow, default actions and cancelable events.

So what does happen step-by-step?

  1. You click on the checkbox
  2. It gets checked
  3. The event is dispatched on the document root
  4. (Not in IE): capture phase, nothing happens with your handlers
  5. The event arrives at the <input>
  6. …and begins to bubble
  7. On the <div>, it is handled. Your event listener calls the preventDefault method, setting an internal cancelled flag.
  8. It bubbles on, but nothing happens any more.
  9. Since the event was cancelled, the default action should not occur and the checkbox is reset to its previous state.

If you uncomment the second part of your code, steps 6+ look different:

  1. The event is handled on the <input>. Your listener calls the stopPropagation method
  2. …which leads to skipping the bubbling phase. (The div-listener will never be called)
  3. The default action was not prevented, and the checkbox stays checked.

这篇关于为什么在父元素上单击“禁用"复选框会使用 preventDefault()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆