什么是Event.target和Event.currentTarget
这个两个target在JavaScript事件处理中十分重要,来看一下他们之间的区别。
event.target
:触发事件的元素event.currentTarget
:绑定事件的元素
二者之间的区别只有在元素嵌套的时候,才会有所体现。比如下面的代码:
外层div1绑定了click事件,内层div2没有绑定任何事件。当我们点击div2的时候,会输出什么呢?
1 | <div id="div1">div 1 |
1 | const div1 = document.getElementById("div1"); |
- 当我们点击
div2
的时候,event.target
是div2
,event.currentTarget
是div1
。 - 当我们点击
div1
的时候,event.target
是div1
,event.currentTarget
也是div1
。
由此可见,event.target
永远是触发事件的元素,而event.currentTarget
永远是绑定事件的元素。
如何禁止子元素触发事件
那么问题来了,有些时候我们不像让内部元素(子元素)触发事件,而是想让外部元素(父元素)触发事件,这个时候我们应该怎么做呢?考虑如下场景,假设现在我们要实现一个Card,这个Card内部有很多子元素,现在用户有一个需求,让Card实现拖拽功能,那么我们需要监听Card的dragenter
事件,但是我们不想让Card内部的子元素触发dragenter
事件,这个时候我们应该怎么做呢?我们可以通过判断event.currentTarget
来实现这个功能,因为event.currentTarget
会指向card本身,而不是其内部的子元素。
其实还有一个更加彻底的办法就是使用CSS的pointer-events
属性,这个属性可以控制元素是否可以触发鼠标事件,比如上面的例子,我们可以这样禁止div2触发click事件:
1 | <div id="div1">div 1 |
这下我们再次点击div2时,输出就变成了下面这样:可见div2没有触发click事件,而是由它的父元素div1触发了。
1 | target: 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
表示被拖拽元素正在离开的元素。