React基础之事件机制
?
某次被問到?React事件機制的問題,關(guān)于這一塊我確實不怎么清楚,因為平時大部分工作都是用?Vue,對于?React的熟悉程度只限于會
Vue通過編譯模板,解析出事件指令,將事件和事件回調(diào)附加到?vnode tree上,在?patch過程中的創(chuàng)建階段和更新階段都會對這個?vnode tree進行處理,拿到每個?vnode上附加的事件信息,就可以調(diào)用原生?DOM API對相應(yīng)事件進行注冊或移除,流程還是比較清晰的,而React則是單獨實現(xiàn)了一套事件機制
在?react源碼的?react-dom/src/events/ReactBrowserEventEmitter.js文件的開頭,看了一些源碼和一些注釋太多了也沒有仔細(xì)研究,然后從網(wǎng)上也是總結(jié)了別人的一些總結(jié)如下
?1.React事件使用了事件委托的機制,一般事件委托的作用都是為了減少頁面的注冊事件數(shù)量,減少內(nèi)存開銷,優(yōu)化瀏覽器性能,React這么做也是有這么一個目的,除此之外,也是為了能夠更好的管理事件,實際上,React中所有的事件最后都是被委托到了 document這個頂級DOM上
2.既然所有的事件都被委托到了 document上,那么肯定有一套管理機制,所有的事件都是以一種先進先出的隊列方式進行觸發(fā)與回調(diào)
3.既然都已經(jīng)接管事件了,那么不對事件做些額外的事情未免有些浪費,于是 React中就存在了自己的 合成事件(SyntheticEvent),合成事件由對應(yīng)的 EventPlugin負(fù)責(zé)合成,不同類型的事件由不同的 plugin合成,例如 SimpleEvent Plugin、TapEvent Plugin等
4.為了進一步提升事件的性能,使用了 EventPluginHub這個東西來負(fù)責(zé)合成事件對象的創(chuàng)建和銷毀
?
這里也是有三個面試相關(guān)的題,和答案
一、組件基礎(chǔ)
1. React 事件機制
<div onClick={this.handleClick.bind(this)}>點我</div>
React并不是將click事件綁定到了div的真實DOM上,而是在document處監(jiān)聽了所有的事件,當(dāng)事件發(fā)生并且冒泡到document處的時候,React將事件內(nèi)容封裝并交由真正的處理函數(shù)運行。這樣的方式不僅僅減少了內(nèi)存的消耗,還能在組件掛在銷毀時統(tǒng)一訂閱和移除事件。
? JSX 上寫的事件并沒有綁定在對應(yīng)的真實 DOM 上,而是通過事件代理的方式,將所有的事件都統(tǒng)一綁定在了?document?上。這樣的方式不僅減少了內(nèi)存消耗,還能在組件掛載銷毀時統(tǒng)一訂閱和移除事件。
另外冒泡到?document?上的事件也不是原生瀏覽器事件,而是 React 自己實現(xiàn)的合成事件(SyntheticEvent)。因此我們?nèi)绻幌胍录芭莸脑?#xff0c;調(diào)用?event.stopPropagation?是無效的,而應(yīng)該調(diào)用?event.preventDefault。
實現(xiàn)合成事件的目的如下:
合成事件首先抹平了瀏覽器之間的兼容問題,另外這是一個跨瀏覽器原生事件包裝器,賦予了跨瀏覽器開發(fā)的能力;
對于原生瀏覽器事件來說,瀏覽器會給監(jiān)聽器創(chuàng)建一個事件對象。如果你有很多的事件監(jiān)聽,那么就需要分配很多的事件對象,造成高額的內(nèi)存分配問題。但是對于合成事件來說,有一個事件池專門來管理它們的創(chuàng)建和銷毀,當(dāng)事件需要被使用時,就會從池子中復(fù)用對象,事件回調(diào)結(jié)束后,就會銷毀事件對象上的屬性,從而便于下次復(fù)用事件對象。
二, React的事件和普通的HTML事件有什么不同?
區(qū)別:
對于事件名稱命名方式,原生事件為全小寫,react 事件采用小駝峰;
對于事件函數(shù)處理語法,原生事件為字符串,react 事件為函數(shù);
react 事件不能采用 return false 的方式來阻止瀏覽器的默認(rèn)行為,而必須要地明確地調(diào)用preventDefault()來阻止默認(rèn)行為。
合成事件是 react 模擬原生 DOM 事件所有能力的一個事件對象,其優(yōu)點如下:
?
兼容所有瀏覽器,更好的跨平臺;
將事件統(tǒng)一存放在一個數(shù)組,避免頻繁的新增與刪除(垃圾回收)。
方便 react 統(tǒng)一管理和事務(wù)機制。
事件的執(zhí)行順序為原生事件先執(zhí)行,合成事件后執(zhí)行,合成事件會冒泡綁定到 document 上,所以盡量避免原生事件與合成事件混用,如果原生事件阻止冒泡,可能會導(dǎo)致合成事件不執(zhí)行,因為需要冒泡到document 上合成事件才會執(zhí)行。
?
3. React 組件中怎么做事件代理?它的原理是什么?
React基于Virtual DOM實現(xiàn)了一個SyntheticEvent層(合成事件層),定義的事件處理器會接收到一個合成事件對象的實例,它符合W3C標(biāo)準(zhǔn),且與原生的瀏覽器事件擁有同樣的接口,支持冒泡機制,所有的事件都自動綁定在最外層上。
在React底層,主要對合成事件做了兩件事:
事件委派:?React會把所有的事件綁定到結(jié)構(gòu)的最外層,使用統(tǒng)一的事件監(jiān)聽器,這個事件監(jiān)聽器上維持了一個映射來保存所有組件內(nèi)部事件監(jiān)聽和處理函數(shù)。
自動綁定:?React組件中,每個方法的上下文都會指向該組件的實例,即自動綁定this為當(dāng)前組件。
?
總結(jié)
- 統(tǒng)一的分發(fā)函數(shù)dispatchEvent。
- React的事件對象是合成對象(SyntheticEvent)。
- 幾乎所有的事件都委托到document,達(dá)到性能優(yōu)化的目的。
- 合成事件與原生事件混用要注意React的事件基本都是委托到document。
最后給大家奉上源碼解析的文章鏈接
https://juejin.cn/post/6844903700423507976?share_token=296b0c62-98f7-4b5f-9ccd-316b6fb59067
?
總結(jié)
以上是生活随笔為你收集整理的React基础之事件机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: intel945显卡linux驱动,下载
- 下一篇: dropbear:一个小巧的ssh se