1、React合成事件是什么?
React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范 来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。
2、为什么会有合成事件?
将事件绑定在document - v16/容器元素 - v17统一管理,防止很多事件直接绑定在原生的dom元素上。造成一些不可控的情况
React 想实现一个全浏览器的框架, 为了实现这种目标就需要提供全浏览器一致性的事件系统,以此抹平不同浏览器的差异。
3、深入合成事件
3.1、事件工作流回顾
3.1.1、事件流
DOM2 Events 规范规定事件流分为 3 个阶段:事件捕获、到达目标和事件冒泡。事件捕获最先发生,为提前拦截事件提供了可能。然后,实际的目标元素接收到事件。最后一个阶段是冒泡,最迟要在这个阶段响应事件。以前面那个简单的 HTML 为例
在 DOM 事件流中,实际的目标(元素)在捕获阶段不会接收到事件。这是因为捕获阶段从
document 到再到就结束了。下一阶段,即会在元素上触发事件的“到达目标”阶段,通常在事件处理时被认为是冒泡阶段的一部分。然后,冒泡阶段开始,事件反向传播至文档。
3.1.2、事件委托
因为事件处理程序在现代 Web 应用中可以实现交互,所以很多开发者会错误地在页面中大量使用它们。在创建 GUI 的语言如 C#中,通常会给 GUI 上的每个按钮设置一个 onclick 事件处理程序。这样做不会有什么性能损耗。在 JavaScript 中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多。首先,每个函数都是对象,都占用内存空间,对象越多,性能越差。其次,为指定事件处理程序所需访问 DOM 的次数会先期造成整个页面交互的延迟。只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。
“过多事件处理程序”的解决方案是使用事件委托。事件委托利用事件冒泡,可以只使用一个事件
处理程序来管理一种类型的事件。
3.2、事件差异
3.2.1、合成事件与原生事件的差异
语法不同:事件名称,事件处理函数语法不同
阻止默认行为方式不同
原声可以通过return false / e.preventDefault() 阻止默认行为
合成事件需要使用 e.preventDefault() ,return false 无效 (addEventListener)
3.2.2、React16和17合成事件的差异
React16时事件委托的对象是 document,React17时事件委托的对象是容器组件
这样做是有利于微前端的,微前端一个前端系统中可能有多个应用,
如果继续采取全部绑定在document上,那么可能多应用下会出现问题。
React16时原生事件与React事件执行时,冒泡阶段与捕获阶段没有区分开(原声捕获-> 原声冒泡 -> React捕获 -> React冒泡);React17时优化了合成事件的执行,当与原生事件一起调用时,捕获阶段总是先于冒泡阶段(React捕获 ->原声捕获 -> 原声冒泡 -> React冒泡)
react17废弃了事件池