摘要:渲染過(guò)程我們都知道使用可以使得網(wǎng)頁(yè)的性能有很大的提高,本文具體探究它是通過(guò)什么樣的渲染機(jī)制做到的。也就是說(shuō)如果父節(jié)點(diǎn)不同,將不會(huì)在去對(duì)比子節(jié)點(diǎn)。
React渲染過(guò)程
我們都知道使用React可以使得網(wǎng)頁(yè)的性能有很大的提高,本文具體探究它是通過(guò)什么樣的渲染機(jī)制做到的。
在頁(yè)面一開(kāi)始打開(kāi)的時(shí)候,React會(huì)調(diào)用render函數(shù)構(gòu)建一棵Dom樹(shù),在state/props發(fā)生改變的時(shí)候,render函數(shù)會(huì)被再次調(diào)用渲染出另外一棵樹(shù),接著,React會(huì)用對(duì)兩棵樹(shù)進(jìn)行對(duì)比,找到需要更新的地方批量改動(dòng)。
Diff 算法這個(gè)過(guò)程中,比較兩棵Dom tree高效找出需要更新的地方是很重要的。React基于兩個(gè)假設(shè):
兩個(gè)相同的組件產(chǎn)生類似的DOM結(jié)構(gòu),不同組件產(chǎn)生不同DOM結(jié)構(gòu)
對(duì)于同一層次的一組子節(jié)點(diǎn),它們可以通過(guò)唯一的id區(qū)分
發(fā)明了一種叫Diff的算法,它極大的優(yōu)化了這個(gè)比較的過(guò)程,將算法復(fù)雜度從O(n^3)降低到O(n)。
同時(shí),基于第一點(diǎn)假設(shè),我們可以推論出,Diff算法只會(huì)對(duì)同層的節(jié)點(diǎn)進(jìn)行比較。如圖,它只會(huì)對(duì)顏色相同的節(jié)點(diǎn)進(jìn)行比較。
也就是說(shuō)如果父節(jié)點(diǎn)不同,React將不會(huì)在去對(duì)比子節(jié)點(diǎn)。因?yàn)椴煌慕M件DOM結(jié)構(gòu)會(huì)不相同,所以就沒(méi)有必要在去對(duì)比子節(jié)點(diǎn)了。這也提高了對(duì)比的效率。
下面,我們具體看下Diff算法是怎么做的,這里分為兩種情況考慮
節(jié)點(diǎn)類型不同
節(jié)點(diǎn)類型相同,但是屬性不同
不同節(jié)點(diǎn)類型對(duì)于不同的節(jié)點(diǎn)類型,react會(huì)基于第一條假設(shè),直接刪去舊的節(jié)點(diǎn),新建一個(gè)新的節(jié)點(diǎn)。
比如:
// 由shape1到shape2
React會(huì)直接刪掉A節(jié)點(diǎn)(包括它所有的子節(jié)點(diǎn)),然后新建一個(gè)B節(jié)點(diǎn)插入。
為了驗(yàn)證這一點(diǎn),我打印出了從shape1到shape2節(jié)點(diǎn)的生命周期,gitbub鏈接:
https://github.com/hhhuangqio...
感興趣的可以自己跑一跑代碼~
Shape1 : A is created A render C is created C render C componentDidMount A componentDidMount Shape2 : A componentWillUnmount C componentWillUnmount B is created B render C is created C render C componentDidMount B componentDidMount
由此可以看出,A與其子節(jié)點(diǎn)C會(huì)被直接刪除,然后重新建一個(gè)B,C插入。
相同節(jié)點(diǎn)類型當(dāng)對(duì)比相同的節(jié)點(diǎn)類型比較簡(jiǎn)單,react會(huì)對(duì)比它們的屬性,只改變需要改變的屬性
比如:
這兩個(gè)div中,react會(huì)只更新className的值
這兩個(gè)div中,react只會(huì)去更新color的值
列表比較// 列表一到列表二
從列表一到列表二,只是在中間插入了一個(gè)C,但是如果沒(méi)有key的時(shí)候,react會(huì)把B刪去,新建一個(gè)C放在B的位置,然后重新建一個(gè)節(jié)點(diǎn)B放在尾部。
你說(shuō)什么就是什么咯?!不信的話,我們還是跑一邊代碼,看看生命周期驗(yàn)證一下
列表一: A is created A render B is created B render A componentDidMount B componentDidMount 列表二: A render B componentWillUnmount C is created C render B is created B render A componentDidUpdate C componentDidMount B componentDidMount
當(dāng)節(jié)點(diǎn)很多的時(shí)候,這樣做是非常低效的,所以我們需要給每個(gè)節(jié)點(diǎn)配一個(gè)key,讓react可以識(shí)別出來(lái)哪些節(jié)點(diǎn)是一樣的,不需要重新創(chuàng)建。
配上key之后,在跑一遍代碼看看,
A render C is created C render B render A componentDidUpdate C componentDidMount B componentDidUpdate
果然,配上key之后,列表二的生命周期就如我所愿,只在指定的位置創(chuàng)建C節(jié)點(diǎn)插入。
這里要注意的一點(diǎn)是,key值必須是穩(wěn)定(所以我們不能用Math.random()去創(chuàng)建key),可預(yù)測(cè),并且唯一的。
React整個(gè)的渲染機(jī)制就是在state/props發(fā)生改變的時(shí)候,重新渲染所有的節(jié)點(diǎn),構(gòu)造出新的虛擬Dom tree跟原來(lái)的Dom tree用Diff算法進(jìn)行比較,得到需要更新的地方在批量造作在真實(shí)的Dom上,由于這樣做就減少了對(duì)Dom的頻繁操作,從而提升的性能。
探索性能優(yōu)化但是,是不是真的需要對(duì)所有的節(jié)點(diǎn)都重新渲染一遍呢?
下一篇文章,我們將繼續(xù)探討這個(gè)問(wèn)題~
參考文檔:
http://www.infoq.com/cn/artic...
https://facebook.github.io/re...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/84678.html
摘要:因?yàn)榘姹緦⒄嬲龔U棄這三生命周期到目前為止,的渲染機(jī)制遵循同步渲染首次渲染,更新時(shí)更新時(shí)卸載時(shí)期間每個(gè)周期函數(shù)各司其職,輸入輸出都是可預(yù)測(cè),一路下來(lái)很順暢。通過(guò)進(jìn)一步觀察可以發(fā)現(xiàn),預(yù)廢棄的三個(gè)生命周期函數(shù)都發(fā)生在虛擬的構(gòu)建期間,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段時(shí)間準(zhǔn)備前端招聘事項(xiàng)...
showImg(https://segmentfault.com/img/remote/1460000018716142?w=200&h=200); showImg(https://segmentfault.com/img/remote/1460000018716143);showImg(https://segmentfault.com/img/remote/1460000010953710);...
摘要:前端面試總結(jié)先說(shuō)背景,本人年月畢業(yè),去年十月校招到今年月一直在做前端開(kāi)發(fā)工作,年前打算換工作,就重新梳理下面試考點(diǎn)總結(jié)包含基礎(chǔ),基礎(chǔ),常見(jiàn)算法和數(shù)據(jù)結(jié)構(gòu),框架,計(jì)算機(jī)網(wǎng)絡(luò)相關(guān)知識(shí),可能有的點(diǎn)很細(xì),有的點(diǎn)很大,參考個(gè)人情況進(jìn)行總結(jié),方便對(duì)知識(shí) 前端面試總結(jié) 先說(shuō)背景,本人2018年7月畢業(yè),去年十月校招到今年10月一直在做前端開(kāi)發(fā)工作,年前打算換工作,就重新梳理下面試考點(diǎn)總結(jié)包含: ...
摘要:前端面試總結(jié)先說(shuō)背景,本人年月畢業(yè),去年十月校招到今年月一直在做前端開(kāi)發(fā)工作,年前打算換工作,就重新梳理下面試考點(diǎn)總結(jié)包含基礎(chǔ),基礎(chǔ),常見(jiàn)算法和數(shù)據(jù)結(jié)構(gòu),框架,計(jì)算機(jī)網(wǎng)絡(luò)相關(guān)知識(shí),可能有的點(diǎn)很細(xì),有的點(diǎn)很大,參考個(gè)人情況進(jìn)行總結(jié),方便對(duì)知識(shí) 前端面試總結(jié) 先說(shuō)背景,本人2018年7月畢業(yè),去年十月校招到今年10月一直在做前端開(kāi)發(fā)工作,年前打算換工作,就重新梳理下面試考點(diǎn)總結(jié)包含: ...
摘要:歡迎來(lái)我的個(gè)人站點(diǎn)性能優(yōu)化其他優(yōu)化瀏覽器關(guān)鍵渲染路徑開(kāi)啟性能優(yōu)化之旅高性能滾動(dòng)及頁(yè)面渲染優(yōu)化理論寫(xiě)法對(duì)壓縮率的影響唯快不破應(yīng)用的個(gè)優(yōu)化步驟進(jìn)階鵝廠大神用直出實(shí)現(xiàn)網(wǎng)頁(yè)瞬開(kāi)緩存網(wǎng)頁(yè)性能管理詳解寫(xiě)給后端程序員的緩存原理介紹年底補(bǔ)課緩存機(jī)制優(yōu)化動(dòng) 歡迎來(lái)我的個(gè)人站點(diǎn) 性能優(yōu)化 其他 優(yōu)化瀏覽器關(guān)鍵渲染路徑 - 開(kāi)啟性能優(yōu)化之旅 高性能滾動(dòng) scroll 及頁(yè)面渲染優(yōu)化 理論 | HTML寫(xiě)法...
閱讀 1398·2021-10-27 14:14
閱讀 3660·2021-09-29 09:34
閱讀 2542·2019-08-30 15:44
閱讀 1790·2019-08-29 17:13
閱讀 2631·2019-08-29 13:07
閱讀 955·2019-08-26 18:26
閱讀 3406·2019-08-26 13:44
閱讀 3272·2019-08-26 13:37