五一前幫一個(gè)同學(xué)做模擬面試的時(shí)候,聊到了 React 的合成事件和 JavaScript 原生事件的差異性問題。我發(fā)現(xiàn)很多 React 技術(shù)棧的同學(xué)對這一方面好像理解的并不清楚,所以今天咱們這篇文章主要就來說下這個(gè)問題。

React合成事件 封裝 了原生瀏覽器事件,提供了統(tǒng)一的API接口,使得開發(fā)者無論瀏覽器環(huán)境如何都可以用相同的方式處理事件。這種方法的主要目的是:確保跨瀏覽器的一致性并與 React 的聲明式編程模型和生命周期集成。
JavaScript 中的事件處理程序 由瀏覽器直接提供,與特定的瀏覽器行為密切相關(guān)。不同的瀏覽器可能有不同的實(shí)現(xiàn)和支持級別。
React 合成事件處理所有瀏覽器兼容性問題,為開發(fā)人員提供一個(gè)干凈、一致的事件處理接口。
例如:它標(biāo)準(zhǔn)化了不同瀏覽器之間的事件行為,以事件冒泡和默認(rèn)行為為例,咱們來看下它的實(shí)現(xiàn):
// 構(gòu)造器定義,接收事件配置、目標(biāo)實(shí)例、本地事件和事件目標(biāo)作為參數(shù)function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { this.dispatchConfig = dispatchConfig; // 存儲事件的配置信息,例如事件類型 this._targetInst = targetInst; //存儲觸發(fā)事件的組件實(shí)例 this.nativeEvent = nativeEvent; // 存儲本機(jī)瀏覽器事件對象 this.target = nativeEventTarget; // 存儲事件的原生目標(biāo),即事件最初發(fā)生的多姆元素 this.currentTarget = null; // 處理事件的當(dāng)前多姆元素將在事件處理期間設(shè)置}// SyneticEvents的原型對象,定義所有實(shí)例共享的方法SyntheticEvent.prototype = { // Method to prevent the default event behavior preventDefault: function() { this.defaultPrevented = true; // 標(biāo)志著事件的默認(rèn)行為已被阻止 const event = this.nativeEvent; // 獲取本地事件對象 if (!event) { return; // 如果沒有本地事件對象,則直接返回 } // 如果本機(jī)事件對象支持preventAlert方法,請調(diào)用它以防止默認(rèn)行為 if (event.preventDefault) { event.preventDefault(); } else if (typeof event.returnValue !== 'undefined') { // 與IE8及以下版本兼容 event.returnValue = false; // 在較舊的IE瀏覽器中,使用returnValue= true來防止默認(rèn)行為 } }, // 阻止事件進(jìn)一步傳播的方法 stopPropagation: function() { const event = this.nativeEvent; // 獲取本地事件對象 if (!event) { return; // 如果沒有本地事件對象,則直接返回 } // 如果本機(jī)事件對象支持stopPropagation方法,請調(diào)用它來停止事件冒泡 if (event.stopPropagation) { event.stopPropagation(); } else if (typeof event.cancelBubble !== 'undefined') { // 與IE8及以下版本兼容 event.cancelBubble = true; // 在較舊的IE瀏覽器中,使用cancelBubble=true來停止事件冒泡 } }, // ...};React 合成事件使用 事件池 來提高性能,即:重(chong)用事件對象。
這意味著:事件回調(diào)函數(shù)執(zhí)行后,事件對象的所有屬性都會被清除并回收以供重用,減少垃圾收集和內(nèi)存使用的壓力。
// 事件對象重用和回收的核心邏輯SyntheticEvent.prototype.destructor = function() { this.target = null; this.currentTarget = null; this.dispatchConfig = null; this._targetInst = null; this.nativeEvent = null; this.isDefaultPrevented = false; this.isPropagationStopped = false; // 清除所有屬性....};// Event poolvar eventPool = [];// 從池中檢索事件對象的函數(shù)SyntheticEvent.getPooled = function(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) { if (eventPool.length) { var instance = eventPool.pop(); SyntheticEvent.call(instance, dispatchConfig, targetInst, nativeEvent, nativeEventTarget); return instance; } return new SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget);};// 將事件對象返回到池的函數(shù)SyntheticEvent.release = function(event) { event.destructor(); eventPool.push(event);};而 JavaScript 事件每次觸發(fā)時(shí)都會創(chuàng)建一個(gè)新的事件對象,這可能會增加內(nèi)存使用量和垃圾收集的頻率,特別是當(dāng)事件頻繁觸發(fā)時(shí)(例如:滾動(dòng) 或 輸入)。”
React 通過 JSX語法 允許我們直接在組件的元素上聲明事件處理函數(shù)(合成事件)。
React 會自動(dòng)處理添加和刪除事件監(jiān)聽器,確保組件安裝時(shí)添加監(jiān)聽器,卸載時(shí)刪除監(jiān)聽器,從而避免內(nèi)存泄漏。
export default function Button() { function handleClick() { console.log('click!'); } return <button onClick={handleClick}>點(diǎn)我</button>;}Javascript 事件需要手動(dòng)調(diào)用 addEventListener 添加事件監(jiān)聽器,同樣手動(dòng)調(diào)用removeEventListener 刪除事件監(jiān)聽器:
document.addEventListener('DOMContentLoaded', function() { const button = document.querySelector('button'); button.addEventListener('click', function() { console.log('click'); });});所以,React 的合成事件是 React 提供了一種高度抽象和集成的事件處理方式,并且可以更好地處理瀏覽器兼容性以及優(yōu)化(卸載事件)等問題。它最終依然會被解析成原生事件。
而 JavaScript 原生事件就是瀏覽器所提供的標(biāo)準(zhǔn) API,使用時(shí)需要更多的處理兼容性以及性能等邊緣邏輯。
本文鏈接:http://m.www897cc.com/showinfo-26-86998-0.htmlReact 合成事件和 JavaScript 事件有什么區(qū)別?
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com