React合成事件是指将原生事件合成一个React事件,之所以要封装自己的一套事件机制,目的是为了实现全浏览器的一致性,抹平不同浏览器之间的差异性。比如原生onclick事件对应React中的onClick合成事件。我们先来看一下React事件和原生事件在使用上的区别:
js
const handleClick = (e) => {e.preventDefault();}
// 原生事件
<div onclick="handleClick()"></div>
// React合成事件
<div onClick={HandleCilck}></div>
从中可以看到,React合成事件使用驼峰的命名方式,而原生事件使用全小写的方式;
另外,React事件处理函数使用事件对象形式,原生事件使用字符串的形式。
我们已经知道onClick事件是一个合成事件,那合成事件是如何跟原生事件产生关联的呢?首先我们来复习一下事件流原理:

如上图所示,所谓事件流包括三个阶段:事件捕获、目标阶段和事件冒泡。事件捕获是从外到里,对应图中的红色箭头标注部分window -> document -> html ... -> target,目标阶段是事件真正发生并处理的阶段,事件冒泡是从里到外,对应图中的target -> ... -> html -> document -> window。 React合成事件的工作原理大致可以分为两个阶段:
- 事件绑定
- 事件触发
在React17之前,React是把事件委托在document上的,React17及以后版本不再把事件委托在document上,而是委托在挂载的容器上了,本文以16.x版本的React为例来探寻React的合成事件。当真实的dom触发事件时,此时构造React合成事件对象,按照冒泡或者捕获的路径去收集真正的事件处理函数,在此过程中会先处理原生事件,然后当冒泡到document对象后,再处理React事件。
注:React17中上述案例的执行会有所区别,会先执行所有捕获事件后,再执行所有冒泡事件。
总结
由于事件对象可能会频繁创建和回收在React16.x中,合成事件SyntheticEvent
采用了事件池,合成事件会被放进事件池中统一管理,这样能够减少内存开销。React通过合成事件,模拟捕获和冒泡阶段,从而达到不同浏览器兼容的目的。