在本演示中,如果单击#s2,append将执行两次,但是如果单击触发单击#s2的按钮,append将只执行一次,因为我无法向事件添加新属性当它从代码中触发时。这是预期的行为吗?
(我知道如果我使用e.originalEvent.handled
代替e.handled
,它的工作方式相同(
http://jsbin.com/tirufoqa/1/edit
<div>
<span id='s1'>click s1</span>
<div>
<span id='s2'>click s2</span>
</div>
</div>
$('div').on('click', 'span', function(e){
if(e.handled) return;
e.handled = 1;
$(this).append("*");
});
$('button').click(function(){
$('#s2').click();
});
答案 0 :(得分:1)
这真的很有趣。我想我找到了答案,但需要进行一些挖掘。
为了测试,我在代码中添加了以下几行:
在处理程序之外:
var firstEvent = null;
在div
处理程序中:
alert(e === firstEvent);
firstEvent = e;
当您手动点击跨度时,第二次通过此比较是false
;但是当你用jQuery触发click时,第二次通过这个比较是true
。请参阅here。
在jQuery文件本身,第4715行附近,有以下行:
if ( event[ jQuery.expando ] ) {
return event;
}
这基本上意味着如果event
已经是jQuery.Event对象,那么它返回已经存在的jQuery.Event对象;而如果它当前不是jQuery.Event对象,那么它会生成一个新的jQuery.Event对象,它包含与原始事件相同的属性。
在你的第一个例子中,浏览器触发了两个事件,并且在每种情况下jQuery都会生成一个新的jQuery.Event对象。最终得到两个jQuery.Event对象。
在第二个例子中,jQuery正在模拟事件。第一次,它创建了一个jQuery.Event对象;第二次,它已经有了第一个模拟的jQuery.Event对象,所以它使用它而不是创建一个新对象。
编辑:jQuery&#34;触发器&#34;事件通过计算事件路径将采取的事件路径,然后通过使用.apply(cur, data)
调用处理程序来模拟该级别的事件,这使得this
等于当前元素&#34;冒泡&#34;并传递<{1>} 它收到的所有信息,包括模拟本机事件的jQuery.Event对象。相同的data
传递给每个元素的处理器冒泡DOM(直到它被告知停止冒泡或到达顶部)
结果是,在实际点击时,jQuery在冒泡的每个级别创建一个新的jQuery.Event对象,在这种情况下,相同的jQuery.Event对象被传递到每个级别,因此任何属性你在较低的水平添加仍然会在更高的水平。
答案 1 :(得分:0)
您是否尝试将附加到span#s2
的星号数量限制为与span#s2
上的点击次数相同?
当您单击span#s2
时,事件处理函数会触发两次,因为它嵌套在两个div中,并且每个div都连接到您的事件监听器。
您可以通过将此调用添加到事件处理函数的第一行来停止此传播:
e.stopPropagation();
DEMO:http://jsbin.com/pobig/1/
http://api.jquery.com/event.stopPropagation/ https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation