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



在这个演示中,如果你点击#s2,追加将执行两次,但是如果你点击触发#s2的按钮,追加将只执行一次,因为当它被代码触发时,我不能给事件添加新的属性。这是预期的行为吗?

(我知道如果我使用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();
});

真有意思。我想我找到了答案,但是花了一些时间。

为了进行测试,我在代码中添加了以下几行:

在处理程序之外:

var firstEvent = null;

div处理程序中:

alert(e === firstEvent);
firstEvent = e;

当您手动单击跨度时,第二次通过此比较是false;但是当您使用jQuery触发点击时,第二次通过这种比较是true。看到这里。

在jQuery文件本身中,在第4715行左右,有以下行:

if ( event[ jQuery.expando ] ) {
    return event;
}

这基本上意味着如果event已经是一个jQuery。事件对象,然后它返回已经存在的jQuery。事件对象;然而,如果它目前不是jQuery。Event对象,然后生成一个新的jQuery。事件对象,包含与原始事件相同的属性。

在第一个示例中,两个事件由浏览器触发,在每种情况下,jQuery都会生成一个新的jQuery。从事件对象中取出。最终得到两个jQuery。罢工事件对象。

编辑:浏览器只触发一个事件,但是这个事件由浏览器以其原生形式传递给每个div的处理程序,而不是作为jQuery。事件对象,以及一个新的jQuery。对象是通过复制事件的属性来创建的。

在第二个示例中,jQuery模拟事件。第一次执行时,它创建了一个jQuery。事件对象;第二次执行时,它已经有了jQuery。事件对象,所以它使用它,而不是创建一个新的。

编辑:jQuery通过计算给定事件采取的eventPath来"触发"事件,然后通过调用.apply(cur, data)的处理程序来模拟该级别的事件,这使得this等于"bubble up"中的当前元素,并将收到的所有信息(包括jQuery)传递给data。事件对象,该对象模拟本机事件。同样的data被传递给每个元素的处理程序,使DOM冒泡(直到它被告知停止冒泡或到达顶部)

结果是,对于实际的单击,jQuery创建了一个新的jQuery。Event对象在每一层起泡,在本例中使用相同的jQuery。事件对象被传递到每个级别,因此您在较低级别添加的任何属性仍将在较高级别存在。

您是否试图限制附加到span#s2的星号数量与span#s2上的点击次数相同?

事件处理函数在单击span#s2时触发两次,因为它嵌套在两个div中,并且每个div都连接到事件侦听器。

您可以通过将此调用添加到事件处理函数的第一行来停止此传播:

e.stopPropagation();

演示:http://jsbin.com/pobig/1/

http://api.jquery.com/event.stopPropagation/https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation

最新更新