React合成事件是什么?
React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范 来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。
为什么会有合成事件?
将事件绑定在document - v16/容器元素 - v17统一管理,防止很多事件直接绑定在原生的dom元素上。造成一些不可控的情况
React 想实现一个全浏览器的框架, 为了实现这种目标就需要提供全浏览器一致性的事件系统,以此抹平不同浏览器的差异。
合成事件与原生事件区别
事件名称命名方式不同
事件处理函数写法不同
阻止默认行为方式不同
// 原生事件命名方式 <button onclick="handleClick()">原生事件命名方式</button> //React合成事件命名方式 <button onClick={handleClick}>合成事件命名方式 </button>
// 原生事件处理函数写法 <button onclick="handleClick()">原生事件处理函数写法</button> //React合成事件处理函数写法 <button onClick={handleClick}>React合成事件处理函数写法</button> // 原生事件阻止默认行为方式 <a href="https://www.baidu.com" onclick="console.log('原生事件阻止默认行为'); return false" > 原生事件阻止默认行为 </a> // React合成事件阻止默认行为方式 const handleClick = e => { e.preventDefault(); console.log('合成事件阻止默认行为'); } const clickElement = <a href="https://www.baidu.com" onClick={handleClick}> </a>
React合成事件与原生事件执行顺序?
• React 所有事件都委托在root 对象上;
• 当真实 DOM 元素触发事件,会冒泡到 root 对象后,再处理 React 事件;
• 在捕获阶段,先注册的先执行,且React合成事件先于原生事件执行;冒泡阶段,先注册的后执行,且原生事件先于React事件执行
React合成事件实现原理
事件注册,事件触发
React中模拟冒泡和捕获
原理:收集的事件放在dispatchQueue数组中,而冒泡和捕获的区别在于执行时机和顺序,那么我们只需要对数组按照不同顺序循环执行即可
function processDispatchQueueItemsInOrder( event: ReactSyntheticEvent, dispatchListeners: Array<DispatchListener>, inCapturePhase: boolean, ): void { let previousInstance; if (inCapturePhase) { // 事件捕获倒序循环 for (let i = dispatchListeners.length - 1; i >= 0; i--) { const {instance, currentTarget, listener} = dispatchListeners[i]; if (instance !== previousInstance && event.isPropagationStopped()) { return; } // 执行事件,传入event对象,和currentTarget executeDispatch(event, listener, currentTarget); previousInstance = instance; } } else { // 事件冒泡正序循环 for (let i = 0; i < dispatchListeners.length; i++) { const {instance, currentTarget, listener} = dispatchListeners[i]; // 如果事件对象阻止了冒泡,则return掉循环过程 if (instance !== previousInstance && event.isPropagationStopped()) { return; } executeDispatch(event, listener, currentTarget); previousInstance = instance; } } }
总结
首先会在fiber节点进入render阶段的complete阶段时,将事件监听绑定在root上。然后调用ensureListeningTo进行事件绑定,生成事件合成对象、收集事件、触发真正的事件。