本篇文章参考以下博文
https://www.jianshu.com/p/d3e9b653fa95
阅读本文前,请先复习一下事件冒泡
冒泡,捕获,委托,事件的所有秘密一览无余
最近开发时遇到一个问题,情况如下:
使用antd
的Icon
组件,添加了一个onClick
事件,升级了蚂蚁组件后,onClick
中的e.target.getAttribute()
无法获取到自定义属性,研究一段时间后,总结一下,以便以后学习。
问题定位
先看一下出现问题的代码
<Icon type="right" onClick={this.queryData} mode="right" />
在点击事件中,我想获取到设置给Icon
的自定义属性mode
queryData = (event) => {
let mode = event.target.getAttribute('mode'); //获取当前点击事件的mode属性
if (mode === 'right') {
...
}
}
当时蚂蚁组件的版本是3.5.0,其中Icon
的元素组成如下
一个<i>
标签中加入了伪类元素
升级antd
到3.20.3
版本的时候,Icon
元素组成发生变化了
由原来的伪类元素,改变成了内部<svg>
标签,这个改变对我们有什么影响,接下来我们查看一下源码
return React.createElement(_LocaleReceiver["default"], {
componentName: "Icon"
}, function (locale) {
return React.createElement("i", _extends({ //创建一个i标签
"aria-label": type && "".concat(locale.icon, ": ").concat(type)
}, restProps, {
tabIndex: iconTabIndex,
onClick: onClick, //给i标签绑定上onClick事件
className: classString
}), innerNode);
});
源码中显示,onClick事件是绑定在<i>
标签上的,在3.20.3版本上,我们触发点击事件,其实是点击<svg>
标签,然后通过冒泡,执行到了外层<i>
标签上,而e.target
获取的是引发触发事件的元素,也就是<svg>
,由上面的图片可知,自定义的属性mode
是被添加在<i>
标签上,那自然<svg>
也就获取不到。
event.target.getAttribute('mode'); //svg标签没有被添加mode属性,故获取不到
解决方案
解决方案是将event.target
修改为event.currentTarget
,就可以获取到了。解释一下原因
event.target
是引发触发事件的元素event.currentTarget
是给绑定事件监听的那个对象
上面两句话可能比较绕,不方便记忆,举一个具象的例子
- 有一对父子,父亲如果被打了,会哭
- 儿子继承了父亲被打了就会哭的行为,同时如果儿子哭了,父亲心疼儿子,也会哭
那么现在发现父子俩都在哭,请问是谁被打了?
这个时候就需要用到event.target
与event.currentTarget
来进行区分了
event.target
指向被打的那个人,父亲被打就指向父亲,儿子被打,就指向儿子event.currentTarget
指向被打了会哭这个行为绑定的对象,也就是说event.currentTarget
一直指向父亲
因为父亲绑定了被打了会哭的事件,儿子只是继承,并没有绑定,所以event.currentTarget
只会指向父亲。