【问题标题】:Why does e.currentTarget change with jQuery's event delegation?为什么 e.currentTarget 会随着 jQuery 的事件委托而改变?
【发布时间】:2017-12-03 12:49:03
【问题描述】:

http://jsbin.com/xaguxuhiwu/1/edit?html,js,console,output

  <div id="container">
    <button id="foo">Foo button</button>
    <button id="bar">Bar button</button>
  </div>

$('#container').on('click', function(e) {
  var targetId = e.target.getAttribute('id');
  // Manually do event delegation
  if (targetId === 'foo') {
    var currentId = e.currentTarget.getAttribute('id');
    console.log('without delegation, currentTarget is: ' + currentId);
  }
});

$('#container').on('click', '#foo', function(e) {
    var currentId = e.currentTarget.getAttribute('id');
    console.log('with delegation, currentTarget is: ' + currentId);
});

基本上,我对事件的 e.currentTarget 的理解是它反映了事件冒泡到的点。由于我在 #container 元素上有一个事件侦听器,因此我希望 currentTarget 在这两种情况下都是 container

这对于标准的on 处理程序是正确的,如第一个示例所示。但是,当使用事件委托(第二次点击时的 #foo 参数)时,currentTarget 会变为内部按钮。

为什么e.currentTarget 在两种情况下会发生变化? 具体来说,在后一种情况下,这是否意味着 jQuery 没有将事件监听器放在父 (#container) 元素上?

【问题讨论】:

  • 在第二个函数中,你是在告诉 jquery“当我点击一个 id="foo" 的元素时触发事件,该元素嵌套在 id="container" 元素的某处。另外,由于您正在预加载 html 元素,而不是在 DOM 加载后插入,因此从技术上讲,您不需要 .on,并且在第二个函数中,您可以访问元素 #foo 而无需首先引用元素 #container .
  • 另外,您可以使用this,而不是使用e.currentTarget。使用 vanilla JS,您可以在 jQuery 中将 e.currentTarget.getAttribute('id') 更改为 this.id$(this).attr('id')
  • @AaronEveleth:这不是我对 jQuery 中的.on 的理解。 .on() 应该为前面选择器中的任何元素添加一个侦听器。当您添加第二个参数(也就是使用事件委托)时,我的理解是 jQuery 不会调用回调函数,除非 event.target 匹配选择器。
  • 关于this,我的问题是关于currentTarget。该属性在 DOM 中具有特定的语义。要么 jQuery 出于某种未知原因修改了 currentTarget,要么事件处理程序的实际绑定方式与预期不同。

标签: javascript jquery dom


【解决方案1】:

基本上这是因为幕后的 jQuery 魔法。包装原生事件的 jQuery 事件对象正在更改 currentTarget,这可能更方便。

要访问通常由currentTarget 指向的值,jQuery 事件有delegateTarget

此属性在.delegate().on() 附加的委托事件中最有用,其中事件处理程序附加在正在处理的元素的祖先处。例如,它可用于在委托点识别和删除事件处理程序。

对于直接附加到元素的非委托事件处理程序,event.delegateTarget 将始终等于 event.currentTarget

您可以看到,在originalEvent 中,currentTarget 具有您所期望的值。

$('#container').on('click', function(e) {
    console.log('without delegation:');
    console.log('target: ' + e.target.getAttribute('id'));
    console.log('currentTarget: ' + e.currentTarget.getAttribute('id'));
    console.log('originalEvent.currentTarget: ' + e.originalEvent.currentTarget.getAttribute('id'));
    console.log('delegateTarget: ' + e.delegateTarget.getAttribute('id'));
    console.log('--');
});
$('#container').on('click', '#foo', function(e) {
    console.log('with delegation:');
    console.log('target: ' + e.target.getAttribute('id'));
    console.log('currentTarget: ' + e.currentTarget.getAttribute('id'));
    console.log('originalEvent.currentTarget: ' + e.originalEvent.currentTarget.getAttribute('id'));
    console.log('delegateTarget: ' + e.delegateTarget.getAttribute('id'));
    console.log('--');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
    <button id="foo">Foo button</button>
    <button id="bar">Bar button</button>
</div>

【讨论】:

  • 如果你像我一样是个书呆子,想看看 jQuery 在哪里做这个the source code is within the dispatch section of event.js.
  • 谢谢,这有帮助。我想知道为什么这是由框架完成的?这不是总是这样e.target === e.currentTarget吗?
  • 哦,我躲开了我自己的解决方案。假设您有一个包含三个 div 的层次结构:祖父母、父母和孩子。如果你$('#grandparent').on('click', '#parent', ...),那么 e.target 应该是孩子,e.currentTarget(jquery 之一)将是父母。
  • @AnilRedshift 只是一个猜测,但我怀疑他们可能试图保留过时的 .live 方法的一些行为,我相信该方法使用了不同的事件绑定策略。不过我不确定。
  • 耶,appcompat!!
【解决方案2】:

简单地说,“#foo”是当前的 DOM 元素,因为它是您单击的内容。它只是一个 DOM 元素,其父级(或父级的父级等)恰好是“#container”。

因此,您的问题的答案是“事件冒泡阶段中的当前 DOM 元素”。 [根据 jQuery 文档)是“#foo”。

同样,如果您调用 $(document).on("click","#foo",...,您的 currentTarget 也将是“#foo”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 2022-07-21
    • 2020-03-25
    • 2017-06-22
    • 2013-01-18
    • 1970-01-01
    相关资源
    最近更新 更多