react 合成事件对象中的target与currentTarget为什么都要指向触发的元素

在nativeEvent中target指向的是触发的dom元素,currentTarget指向的是document,
在syntheticEvent 获取到的target currentTarget都是指向当前触发与绑定的元素
那么react 为什么要把currentTarget在syntheticEvent中修改为当前绑定的元素呢?

阅读 3.6k
1 个回答

React 的合成事件是尽量模拟原生事件的行为,所以要理解这几个属性,你需要对浏览器原生事件模型有了解。

原生事件模型中,currentTarget 并非在所有情况下都和 target 指向相同的元素。target 指向的是触发事件的原始元素,而 currentTarget 可能是触发事件的父元素,这个是事件冒泡的机制。假设你有个大 DIV 套小 DIV,你在大 DIV 上绑定 onclick 事件,你点击小 DIV 的区域,这时候 target 是内部的 DIV,而 currentTarget 是当前事件冒泡到的节点,即绑定的元素。react 的合成事件是遵从这个规则的。

而为什么 syntheticEvent.nativeEvent 上的 currentTarget 并不符合原生事件的规则呢?这个是 nativeEvent 更应该正确才对啊。这是因为 React 对事件绑定做了优化,借助事件冒泡 React 其实只要给 document root element 绑定 onclick 就可以处理 App 内所有元素的 click 事件,React 自己再处理事件 冒泡/分发 机制。这就是为什么 syntheticEvent.nativeEvent 上的 currentTarget 一直会是 document 根元素。这样做的好处是 React 可以自己控制整个流程,而且用这种事件代理模式,可以大大降低开销, 包括对原生事件进行一层包装,也都是为了优化。

一个小技巧是 chrome devTools 里可以用 getEventListeners(element) 来获取某个元素上绑定的事件,你会发现即使你在你的 component 里对某 DIV 绑定了 onclick,getEventListeners 仍然返回了空,即说明事件是被根元素代理来运作的。(其实并不,你能看到这个 DIV 绑定了一个 noop 的函数给 click 事件,为了解决 iOS safari 下元素不绑定 click 事件就不可点击的 bug)

对于不可冒泡事件,比如 input focus 之类的,情况就不同了,有兴趣可以试试这种事件的 nativeEvent 上的 target 和 currentTarget。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题