摘要:對同一層級的子節(jié)點進行處理時,會根據(jù)進行簡要的復用。或者直接使用,原理一致。
一、從React原理談起 react是什么?
react是用于構建用戶界面的JS框架。因此react只負責解決view層的渲染。
react做了什么?Virtual Dom模型
生命周期管理
setState機制
diff算法
React patch、事件系統(tǒng)
react的 Virtual Dom模型
virtual dom 實際上是對實際Dom的一個抽象,是一個js對象。react所有的表層操作實際上是在操作virtual dom。
經(jīng)過diff算法會計算出virtual dom的差異,然后將這些差異進行實際的dom操作更新頁面。
react的生命周期 setState機制 理想情況:setState是“異步”的,調(diào)用setState只會提交一次state修改到隊列中,不會直接修改this.state。
等到滿足一定條件時,react會合并隊列中的所有修改,觸發(fā)一次update流程,更新this.state。
因此setState機制減少了update流程的觸發(fā)次數(shù),從而提高了性能。
由于setState會觸發(fā)update過程,因此在update過程中必經(jīng)的生命周期中調(diào)用setState會存在循環(huán)調(diào)用的風險。
另外用于監(jiān)聽state更新完成,可以使用setState方法的第二個參數(shù),回調(diào)函數(shù)。在這個回調(diào)中讀取this.state就是已經(jīng)批量更新后的結果。
特殊情況:在實際開發(fā)中,setState的表現(xiàn)有時會不同于理想情況。主要是以下兩種。
在mount流程中調(diào)用setState。
在setTimeout/Promise回調(diào)中調(diào)用setState。
在第一種情況下,不會進入update流程,隊列在mount時合并修改并render。
在第二種情況下,setState將不會進行隊列的批更新,而是直接觸發(fā)一次update流程。
這是由于setState的兩種更新機制導致的,只有在批量更新模式中,才會是“異步”的。
diff算法diff算法用于計算出兩個virtual dom的差異,是react中開銷最大的地方。
傳統(tǒng)diff算法通過循環(huán)遞歸對比差異,算法復雜度為O(n3)。
react diff算法制定了三條策略,將算法復雜度從 O(n3)降低到O(n)。
WebUI中DOM節(jié)點跨節(jié)點的操作特別少,可以忽略不計。
擁有相同類的組件會擁有相似的DOM結構。擁有不同類的組件會生成不同的DOM結構。
同一層級的子節(jié)點,可以根據(jù)唯一的ID來區(qū)分。
針對這三個策略,react diff實施的具體策略是:
diff對樹進行分層比較,只對比兩棵樹同級別的節(jié)點??鐚蛹壱苿庸?jié)點,將會導致節(jié)點刪除,重新插入,無法復用。
diff對組件進行類比較,類相同的遞歸diff子節(jié)點,不同的直接銷毀重建。diff對同一層級的子節(jié)點進行處理時,會根據(jù)key進行簡要的復用。兩棵樹中存在相同key的節(jié)點時,只會移動節(jié)點。
另外,在對比同一層級的子節(jié)點時:
diff算法會以新樹的第一個子節(jié)點作為起點遍歷新樹,尋找舊樹中與之相同的節(jié)點。
如果節(jié)點存在,則移動位置。如果不存在,則新建一個節(jié)點。
在這過程中,維護了一個字段lastIndex,這個字段表示已遍歷的所有新樹子節(jié)點在舊樹中最大的index。
在移動操作時,只有舊index小于lastIndex的才會移動。
這個順序優(yōu)化方案實際上是基于一個假設,大部分的列表操作應該是保證列表基本有序的。
可以推倒倒序的情況下,子節(jié)點列表diff的算法復雜度為O(n2)
由于react中性能主要耗費在于update階段的diff算法,因此性能優(yōu)化也主要針對diff算法。
1.減少diff算法觸發(fā)次數(shù)減少diff算法觸發(fā)次數(shù)實際上就是減少update流程的次數(shù)。
正常進入update流程有三種方式:
setState機制在正常運行時,由于批更新策略,已經(jīng)降低了update過程的觸發(fā)次數(shù)。
因此,setState優(yōu)化主要在于非批更新階段中(timeout/Promise回調(diào)),減少setState的觸發(fā)次數(shù)。
常見的業(yè)務場景即處理接口回調(diào)時,無論數(shù)據(jù)處理多么復雜,保證最后只調(diào)用一次setState。
父組件的render必然會觸發(fā)子組件進入update階段(無論props是否更新)。此時最常用的優(yōu)化方案即為shouldComponentUpdate方法。
最常見的方式為進行this.props和this.state的淺比較來判斷組件是否需要更新?;蛘咧苯邮褂肞ureComponent,原理一致。
需要注意的是,父組件的render函數(shù)如果寫的不規(guī)范,將會導致上述的策略失效。
// Bad case // 每次父組件觸發(fā)render 將導致傳入的handleClick參數(shù)都是一個全新的匿名函數(shù)引用。 // 如果this.list 一直都是undefined,每次傳入的默認值[]都是一個全新的Array。 // hitSlop的屬性值每次render都會生成一個新對象 class Father extends Component { onClick() {} render() { returnforceUpdatethis.onClick()} list={this.list || []} hitSlop={{ top: 10, left: 10}}/> } } // Good case // 在構造函數(shù)中綁定函數(shù),給變量賦值 // render中用到的常量提取成模塊變量或靜態(tài)成員 const hitSlop = {top: 10, left: 10}; class Father extends Component { constructor(props) { super(props); this.onClick = this.onClick.bind(this); this.list = []; } onClick() {} render() { return } }
其中forceUpdate方法調(diào)用后將會直接進入componentWillUpdate階段,無法攔截,因此在實際項目中應該棄用。
其他優(yōu)化策略shouldComponentUpdate
使用shouldComponentUpdate鉤子,根據(jù)具體的業(yè)務狀態(tài),減少不必要的props變化導致的渲染。如一個不用于渲染的props導致的update。
另外, 也要盡量避免在shouldComponentUpdate 中做一些比較復雜的操作, 比如超大數(shù)據(jù)的pick操作等。
合理設計state,不需要渲染的state,盡量使用實例成員變量。
不需要渲染的props,合理使用context機制,或公共模塊(比如一個單例服務)變量來替換。
2.正確使用diff算法不使用跨層級移動節(jié)點的操作。
對于條件渲染多個節(jié)點時,盡量采用隱藏等方式切換節(jié)點,而不是替換節(jié)點。
盡量避免將后面的子節(jié)點移動到前面的操作,當節(jié)點數(shù)量較多時,會產(chǎn)生一定的性能問題。
未完待續(xù)文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/96165.html
摘要:對同一層級的子節(jié)點進行處理時,會根據(jù)進行簡要的復用。二性能優(yōu)化方案由于中性能主要耗費在于階段的算法,因此性能優(yōu)化也主要針對算法。此時最常用的優(yōu)化方案即為方法?;蛘咧苯邮褂?,原理一致。 一、從React原理談起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于構建用戶界面的JS框架...
摘要:歡迎來我的個人站點性能優(yōu)化其他優(yōu)化瀏覽器關鍵渲染路徑開啟性能優(yōu)化之旅高性能滾動及頁面渲染優(yōu)化理論寫法對壓縮率的影響唯快不破應用的個優(yōu)化步驟進階鵝廠大神用直出實現(xiàn)網(wǎng)頁瞬開緩存網(wǎng)頁性能管理詳解寫給后端程序員的緩存原理介紹年底補課緩存機制優(yōu)化動 歡迎來我的個人站點 性能優(yōu)化 其他 優(yōu)化瀏覽器關鍵渲染路徑 - 開啟性能優(yōu)化之旅 高性能滾動 scroll 及頁面渲染優(yōu)化 理論 | HTML寫法...
摘要:工程實踐立足實踐,提示實際水平內(nèi)聯(lián)函數(shù)與性能很多關于性能優(yōu)化的文章都會談及內(nèi)聯(lián)函數(shù),其也是常見的被詬病為拖慢性能表現(xiàn)的元兇之一不過本文卻是打破砂鍋問到底,論證了內(nèi)聯(lián)函數(shù)并不一定就會拖慢性能,過度的性能優(yōu)化反而會有損于應用性能。 showImg(https://segmentfault.com/img/remote/1460000011481413?w=1240&h=825); 前端每周...
閱讀 2096·2021-11-08 13:14
閱讀 2995·2021-10-18 13:34
閱讀 2099·2021-09-23 11:21
閱讀 3659·2019-08-30 15:54
閱讀 1831·2019-08-30 15:54
閱讀 2994·2019-08-29 15:33
閱讀 2662·2019-08-29 14:01
閱讀 2018·2019-08-29 13:52