0%

event.target-vs-event.currentTarget

什么是Event.target和Event.currentTarget

这个两个target在JavaScript事件处理中十分重要,来看一下他们之间的区别。

  • event.target:触发事件的元素
  • event.currentTarget:绑定事件的元素

二者之间的区别只有在元素嵌套的时候,才会有所体现。比如下面的代码:
外层div1绑定了click事件,内层div2没有绑定任何事件。当我们点击div2的时候,会输出什么呢?

1
2
3
<div id="div1">div 1
<div id="div2">div2</div>
</div>
1
2
3
4
5
const div1 = document.getElementById("div1");
div1.addEventListener("click", (event) => {
console.log(event.target);
console.log(event.currentTarget);
});

event-target-vs-event-currentTarget

  • 当我们点击div2的时候,event.targetdiv2event.currentTargetdiv1
  • 当我们点击div1的时候,event.targetdiv1event.currentTarget也是div1

由此可见,event.target永远是触发事件的元素,而event.currentTarget永远是绑定事件的元素。

如何禁止子元素触发事件

那么问题来了,有些时候我们不像让内部元素(子元素)触发事件,而是想让外部元素(父元素)触发事件,这个时候我们应该怎么做呢?考虑如下场景,假设现在我们要实现一个Card,这个Card内部有很多子元素,现在用户有一个需求,让Card实现拖拽功能,那么我们需要监听Card的dragenter事件,但是我们不想让Card内部的子元素触发dragenter事件,这个时候我们应该怎么做呢?我们可以通过判断event.currentTarget来实现这个功能,因为event.currentTarget会指向card本身,而不是其内部的子元素。

其实还有一个更加彻底的办法就是使用CSS的pointer-events属性,这个属性可以控制元素是否可以触发鼠标事件,比如上面的例子,我们可以这样禁止div2触发click事件:

1
2
3
<div id="div1">div 1
<div id="div2" style="pointer-events: none;">div2</div>
</div>

这下我们再次点击div2时,输出就变成了下面这样:可见div2没有触发click事件,而是由它的父元素div1触发了。

1
2
target: div 1
currentTarget: div 1

需要注意:pointer-events属性是CSS3中的属性,IE11及以下版本不支持。并且它具有传递性,比如我们在div2上设置了pointer-events: none;,那么div2及其子元素都不会触发鼠标事件。

Event.relatedTarget

Event中除了这两个target之外,其实还有一个relatedTarget属性,这个属性在不同的事件中有不同的含义,比如在mouseover事件中,relatedTarget表示鼠标移入的元素,而在mouseout事件中,relatedTarget表示鼠标移出的元素。两外html5中的drag and drop api也会用到这个属性,比如在dragenter事件中,relatedTarget表示被拖拽元素正在进入的元素,而在dragleave事件中,relatedTarget表示被拖拽元素正在离开的元素。

References