496

谁能通过示例告诉我JavaScript 事件中的currentTargettarget属性之间的确切区别以及在哪种情况下使用哪个属性?

4

9 回答 9

686

默认情况下,事件冒泡。所以两者的区别是:

  • target是触发事件的元素(例如,用户点击)
  • currentTarget是事件侦听器附加到的元素。
于 2012-04-10T09:50:41.483 回答
137

target= 触发事件的元素。

currentTarget= 具有事件侦听器的元素。

于 2016-02-24T08:57:57.573 回答
53

最小可运行示例

window.onload = function() {
  var resultElem = document.getElementById('result')
  document.getElementById('1').addEventListener(
    'click',
    function(event) {
      resultElem.innerHTML += ('<div>target: ' + event.target.id + '</div>')
      resultElem.innerHTML += ('<div>currentTarget: ' + event.currentTarget.id + '</div>')
    },
    false
  )
  document.getElementById('2').dispatchEvent(
          new Event('click', { bubbles:true }))
}
<div id="1">1 click me
  <div id="2">2 click me as well</div>
</div>
<div id="result">
  <div>result:</div>
</div>

如果点击:

2 click me as well

然后1听它,并附加到结果:

target: 2
currentTarget: 1

因为在那种情况下:

  • 2是引发事件的元素
  • 1是监听事件的元素

如果点击:

1 click me

相反,结果是:

target: 1
currentTarget: 1

在铬 71 上测试。

于 2016-06-01T20:27:56.267 回答
27

如果这不坚持,试试这个:

current incurrentTarget指的是现在。这是捕捉从其他地方冒出的事件的最新目标。

于 2016-05-02T21:49:28.647 回答
16

对于气泡为的事件true,它们会冒泡。

大多数事件都会冒泡,除了几个,即focusblurmouseentermouseleave,...

如果事件evt冒泡,evt.currentTarget则在其冒泡路径中更改为当前目标,而evt.target保留与触发事件的原始目标相同的值。

事件的目标类型

值得注意的是,如果您的事件处理程序(冒泡的事件)是异步的,并且处理程序使用evt.currentTarget. currentTarget应该在本地缓存,因为事件对象在冒泡链(codepen)中被重用。

const clickHandler = evt => {
  const {currentTarget} = evt // cache property locally
  setTimeout(() => {
    console.log('evt.currentTarget changed', evt.currentTarget !== currentTarget)
  }, 3000)
}

如果您使用 React,从 v17 开始,react 会删除事件池

因此,事件对象在处理程序中被刷新,并且可以安全地用于异步调用 ( codepen )。

↑并不总是正确的。onClick事件currentTargetundefined在事件处理程序完成之后。总之,如果要在同步调用后使用事件属性,请始终在本地缓存它们。

来自反应文档

笔记:

从 v17 开始, e.persist() 不会做任何事情,因为 SyntheticEvent 不再被池化。

还有很多其他的东西太长无法粘贴在答案中,所以我在这里总结并发了一篇博文

于 2020-12-20T07:34:21.200 回答
12

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

如果单击上面代码中的 P 标签,您将收到三个警报,如果您单击 div 标签,您将收到两个警报和一个单击表单标签的警报。现在看到下面的代码,

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>
<script>
function fun(event){
  alert(event.target+" "+event.currentTarget);
}

</script>

<form>FORM
  <div onclick="fun(event)">DIV
    <p>P</p>
  </div>
</form>
我们刚刚从 P 和 form 标签中删除了 onclick,现在当我们点击 P 标签时,我们只收到一个警报:

[对象 HTMLParagraphElement] [对象 HTMLDivElement]

这里 event.target 是 [object HTMLParagraphElement],而 event.curentTarget 是 [object HTMLDivElement]: 所以

event.target 是事件起源的节点,而 event.currentTarget 相反,是指附加当前事件侦听器的节​​点。要了解更多信息,请参阅冒泡

在这里,我们点击了 P 标签,但我们在 P 上没有侦听器,但在其父元素 div 上。

于 2017-11-21T06:31:17.000 回答
6

event.target是事件起源的节点,即。无论您将事件侦听器放置在何处(在段落或跨度上), event.target 都指的是节点(用户单击的位置)。

相反, event.currentTarget指的是附加了当前事件侦听器的节​​点。IE。如果我们在段落节点上附加了我们的事件监听器,那么 event.currentTarget 指的是段落,而 event.target 仍然指的是跨度。注意:如果我们在 body 上也有一个事件监听器,那么对于这个事件监听器,event.currentTarget 指的是 body(即,作为事件监听器的输入提供的事件在每次事件冒泡一个节点时更新)。

于 2017-04-10T08:58:04.010 回答
5

Event.currentTarget事件处理程序已附加到的元素,而不是Event.target,它标识事件发生的元素并且可能是它的后代

来源:MDN

target总是指前面的元素addEventListener——它是事件起源的元素。 currentTarget告诉你 - 如果这是一个冒泡的事件 - 当前附加了事件侦听器的元素(如果事件发生,它将触发事件处理程序)。

有关示例,请参阅此 CodePen。如果您打开开发人员工具并单击方块,您会看到首先 div 是目标和 currentTarget,但事件会冒泡到主元素 - 然后主元素成为 currentTarget,而 div 仍然是目标. 请注意,事件侦听器需要附加到两个元素才能发生冒泡。

于 2021-05-03T00:05:31.810 回答
2

这是一个简单的场景来解释为什么需要它。假设您使用以下格式向用户显示了一些消息,但您也希望给他们关闭它们的自由(除非您有特殊的精神障碍),所以这里有一些消息窗格:

[此窗格中将显示一条消息 [x]]

[此窗格中将显示一条消息 [x]]

[此窗格中将显示一条消息 [x]]

并且当用户单击每个上的[x]按钮时,必须删除整个相应的窗格。

这是窗格的 HTML 代码:

<div class="pane">
  A message will be here
  <span class="remove-button">[x]</span>
</div>

现在你想在哪里添加点击事件监听器?用户单击[x],但您想删除窗格,因此:

  • 如果将 click 事件侦听器添加到[x],那么您将不得不在 DOM 上找到它的父级并将其删除......这可能但丑陋且“依赖于 DOM”。

  • 如果您将 click 事件侦听器添加到窗格,单击“窗格上的任何位置”将删除它,而不仅仅是单击其[x]按钮。

所以,我们能做些什么?我们可以使用事件系统的“冒泡”功能:

“无论是否存在任何事件处理程序,都会引发事件并在 DOM 树中冒泡。”

在我们的示例中,这意味着即使我们将事件处理程序添加到窗格中,我们也将能够捕获专门由单击 [x] 按钮引发的事件(因为事件会冒泡)。因此,引发事件的位置与我们捕获和处理它的位置之间可能存在差异。

它被提出的地方将在 中event.target,它被捕获的地方将在event.currentTarget(我们目前正在处理它的地方)。所以:

let panes = document.getElementsByClassName("pane");
for(let pane of panes){
    pane.addEventListener('click', hndlr);
}
function hndlr(e){
    if(e.target.classList.contains('remove-button')){
        e.currentTarget.remove();
    }
}

(这个例子的功劳归功于网站JavaScript.info

于 2021-05-27T15:16:01.997 回答