最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does preventDefault() on a parent element's click 'disable' a checkbox? - Stack Overflo

programmeradmin0浏览0评论

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?

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?

Share Improve this question asked Apr 2, 2013 at 14:42 peteorpeterpeteorpeter 4,0973 gold badges30 silver badges47 bronze badges 2
  • 5 This is the intended behavior of preventDefault(). It doesn't matter what node the eventObject is bubbling through, it's still the same object. – Brad M Commented Apr 2, 2013 at 14:46
  • Funny thing is that you actually provided the right answer :-) For people more acknowledged in event handling, this is a quick one :-) – jave.web Commented Apr 24, 2016 at 20:06
Add a comment  | 

2 Answers 2

Reset to default 13

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 prevents the browser's default action from being fired. Changing the checked state of a checkbox or following the href of an anchor, submitting a form, etc., are default actions. preventDefault prevents them, while allowing event propagation.

This is distinct from event propagation, (which you may – as you've noted – stop by stopPropagation). The event will propagate throughout the entire hierarchy of listeners before invoking the browser's default behavior (unless prevented).

发布评论

评论列表(0)

  1. 暂无评论