最近做项目的时候发现了一个问题,在document
上绑定clcik
事件后,input type
为checkbox
或radio
的状态不会改变,但是绑定的事件会执行,Demo如下:
可以看到,在执行完$(this).attr('checked',true);
后到alert
时,checkbox
的状态是选中的,而且弹出的状态也是checked
,也就是说,这个时候,checkbox
是选中的。但是为什么我们在点击确定之后,checkbox
又变回了未选中了呢?在相应事件结束之后,一定还有什么东西让它改回去了?其实,这是checkbox
的默认click
事件的做的。也许大家会问,我不是通过e.preventDefault()
把默认事件去掉了吗?为什么还有默认事件?难道e.preventDefault()
没有生效?
在这里需要说明下:一般的默认事件,会在我们绑定的响应事件之后执行(这样说不准确,默认事件和自己绑定的响应事件是在一起执行的,只不过,它的真正的作用一般会在所有事件内容做完之后才会体现出来,因此,在这就简单理解成在绑定的事件之后执行吧)。有了这个说明,我们再来说下这个现象。这不是浏览器的bug,也不是没有禁掉默认事件。由于checkbox
是系统的组件,因此它的实现机理比较复杂,在这里不讨论,这个问题的主要原因是:checkbox的click事件的默认事件是将修改的选中状态生效
。解释一下,如果在鼠标点击之前,checkbox
的状态是选中,那么在点击checkbox
时,它会将当前的状态取反即取消选中,然后执行响应事件,最后默认事件将这个状态生效。
上面的这个代码中,由于去掉了默认事件,因此,在执行响应事件时,checkbox
确实选中了,aler
t出来的也是选中的,但是在事件结束时,由于没有没有默认事件,那么这个checkbox
就回到了点击之前的状态。我们如果将input
写成:<input type="checkbox" id="id1" checked />
,即在点击之前就选中它,那么点击之后,checkbox
就是选中的状态了。当然,这个选中状态不是因为$(this).attr('checked',true);
造成的,而是没有默认事件,它又重置回之前的状态了。这里我们将代码改成$(this).attr('checked',false);
在执行完之后,仍然会是选中状态的。
这个问题充分体现出了默认事件的重要性,我们之前去掉过很多默认事件,但是大部分的默认事件如我们想象的那样,去掉之后,基本功能就不存在了。但是checkbox
的click
默认事件不是让它没有反应,而是将修改后的状态生效(注意:仅仅是click
事件,mousedown
和mouseup
事件是没有这个特点的)。因此,在我们不知道这个问题之前,如果禁掉了它的click
事件,就会出现一些问题了。当然,这知识针对checkbox
和radio
而言。w3c的文档也证实了这一点,它的文档上有明确的说明:
Note: During the handling of a click event on an input element with a type attribute that has the value “radio” or “checkbox”, some implementations may change the value of this property before the event is being dispatched in the document. If the default action of the event is canceled, the value of the property may be changed back to its original value. This means that the value of this property during the handling of click events is implementation dependent.
原文地址:http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-6043025