我可以向从代码触发的事件添加新属性吗?

时间:2014-07-25 23:20:37

标签: javascript jquery event-handling

在本演示中,如果单击#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();
});

2 个答案:

答案 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对象。

编辑:浏览器只触发了一个事件,但是一个事件由浏览器以其本机形式传递给每个div处理程序,而不是作为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