持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
什么是合成事件
合成事件的底层仍然是 DOM 事件,但隐藏了很多复杂性和跨浏览器时的不一致性,更易于在 React 框架中使用。React 会传入一个描述点击事件的对象作为事件函数的第一个参数。而这个对象就是 React 中的合成事件(SyntheticEvent)。
合成事件是原生 DOM 事件的一种包装,它与原生事件的接口相同,根据 W3c 规范,React 内部规范化(Normalize)了这些接口在不同浏览器之间的行为,开发者不用再担心事件处理的浏览器兼容性问题。
特定事件的行为不同
React 合成事件规范化了一些在各个浏览器间行为不一致,甚至是在不同元素上行为不一致的事件,其中有代表性的是 onChange 。在 Chrome 或 Firefox 中,一个文本框 的 change 事件发生在文本框内容被改变、然后失去焦点的时候。不过,对一个下拉框 的change 事件,Chrome 和老版本 Firefox(v63 以前)就有分歧了,前者每次按下键盘箭头键都会触发 change 事件,但后者只有下拉框失去焦点时才会触发。
而在 React 中, <input>、<textarea>和<select>三种表单元素的onChange 合成事件被规范成了一致的行为:在不会导致显示抖动的前提下,表单元素值的改变会尽可能及时地触发这一事件。以文本框为例,同样是输入一句话,合成 change 事件发生的次数要多于原生的次数,在onChange 事件处理函数被调用时,传入的事件对象参数提供的表单元素值也尽可能是最新的。顺便提一下,原生 change 事件行为的不一致,只是前端领域浏览器兼容性问题的冰山一角。
除了 onChange ,合成事件也规范化了 onBeforeInput 、 onMouseEnter 、 onMouseLeave 、 onSelect 。
实际注册的目标 DOM 元素不同
React 使用了事件代理模式。React 在创建根( createRoot )的时候,会在容器上监听所有自己支持的原生 DOM 事件。当原生事件被触发时,React 会根据事件的类型和目标元素,找到对应的 FiberNode 和事件处理函数,创建相应的合成事件并调用事件处理函数。