問(wèn)題的開(kāi)始
由setState 引出
問(wèn):setState 是同步的是還異步的?
答:在React合成事件中是異步的,在原生事件中是同步的。
那么甫题,React 合成事件是什么呢?
React 自己實(shí)現(xiàn)了一套高效的事件注冊(cè)涂召,存儲(chǔ)幔睬,分發(fā)和重用邏輯,在DOM事件體系基礎(chǔ)上做了很大改進(jìn)芹扭,減少了內(nèi)存消耗麻顶,簡(jiǎn)化了事件邏輯。它有如下特點(diǎn):
- 事件綁定在document上
2.自身實(shí)現(xiàn)了一套冒泡機(jī)制舱卡,在冒泡階段處理事件
3.有一套自己的合成事件
4.用對(duì)象池來(lái)管理合成事件對(duì)象的創(chuàng)建和銷(xiāo)毀辅肾,這樣減少了垃圾的生成和新對(duì)象內(nèi)存的分配,大大提高了性能
事件觸發(fā)過(guò)程
當(dāng)事件觸發(fā)的時(shí)候轮锥,我們的組件會(huì)生成一個(gè)合成事件矫钓,然后傳遞到document當(dāng)中,document會(huì)通過(guò)dispatchEvent 回調(diào)函數(shù)依次執(zhí)行dispatchListerner中同類(lèi)型事件的監(jiān)聽(tīng)函數(shù)。
事件注冊(cè)
事件注冊(cè)是在組件生成的時(shí)候新娜,我們將Virtual DOM 中的所有事件對(duì)應(yīng)的原生事件都注冊(cè)在document 的一個(gè)監(jiān)聽(tīng)器中( ListernerBank)
事件對(duì)象可能會(huì)被頻繁創(chuàng)建和回收赵辕,因此 React 引入事件池,在事件池中獲取或釋放事件對(duì)象概龄。即 React 事件對(duì)象不會(huì)被釋放掉还惠,而是存放進(jìn)一個(gè)數(shù)組中,當(dāng)事件觸發(fā)私杜,就從這個(gè)數(shù)組中彈出蚕键,避免頻繁地去創(chuàng)建和銷(xiāo)毀(垃圾回收)。
在 React 中衰粹,“合成事件”會(huì)以事件委托[Event Delegation]方式綁定在組件最上層锣光,并在組件卸載(unmount)階段自動(dòng)銷(xiāo)毀綁定的事件。
React 所有事件都掛載在 document 對(duì)象上铝耻;
當(dāng)真實(shí) DOM 元素觸發(fā)事件誊爹,會(huì)冒泡到 document 對(duì)象后,再處理 React 事件瓢捉;
所以會(huì)先執(zhí)行原生事件频丘,然后處理 React 事件;
最后真正執(zhí)行 document 上掛載的事件泊柬。