React元件的效能優化方法
1. 單一React元件的效能最佳化
React利用Virtual DOM來提升渲染效能,雖然每一次頁面更新都是最元件的從新渲染,但並不是將之前的渲染內容全部拋棄重來,借助Virtual DOM,React能夠計算出對DOM樹的最少修改,這就是React默認情況下渲染都很迅速的秘訣;
不過,雖然Virtual DOM能夠將每次DOM操作量減少到最小,但,計算和比較Virtual DOM依然是一個複雜的過程;
當然,如果能夠在開始計算Virtual DOM之前就判斷渲染的結果不會有變化,那麼就可以不進行Virtual DOM計算和比較,速度就會更快。
2.shouldComponentUpdate的預設實作方式
既然可以對元件在開始計算Virtual DOM之前判斷渲染結果不會有變化時,阻止渲染的進行,從而提升效能,那麼我們自然想到使用shouldComponentUpdate(nextProp,nextState)
shouldComponentUpdate函數在render函數之前調用,決定「什麼時候不需要從新渲染」;
即傳回一個布林值,決定更新是否進行下去,預設回傳true,若回傳false則中斷更新;
shouldComponentUpdate(nextProp,nextState){ return (nextProp.completed !== this.props.completed) || (nextProp.text !== this.props.text) }
其中nextProps為此次更新傳入的props,對於這個元件,影響渲染內容的prop只有completed和text,只要確保這兩個prop沒有變化,shouldComponentUpdate就可以返回false阻止沒必要的更新
#但是,上述的比較只是'淺層比較',如果類型是基本類型,只要值相同,那麼“淺層比較”
也會認為二者相同:
#那,如果prop的型別是複雜的物件怎麼辦?
對於複雜對象,'淺層比較'的方式只看這兩個prop是不是同一個對象的引用,如果不是,哪怕對像中的內容完全一樣也會認為是不同的兩個prop。那麼使用“深層比較”:但對物件的結構是無法預測的,如果遞歸對每個字段都進行“深層比較”,不光會讓程式碼更加複雜,也可能會造成效能問題。
所以,要判斷前後的物件類型的prop是相同的,就必須保證prop是指向同一個JavaScript物件:
<Foo styleProp = {{color: "red"}}>
要避免使用上面的傳入方式,應為每次渲染都會重新建立{color: "red"}對象,引用位址每次都不同,將導致每次的styleProp都不同。
const footStyle = {color: "red"};//确保这个初始化只执行一次,不要放在render函数中 <Foo styleProp = {footStyle}>
使用‘單例模式'確保傳入的styleProp指向同一個物件
如果是函數呢?
<Foo onToggle={() => onToggleTodo(item.id)}/>
應該避免使用上面的函數傳遞模式,因為這裡賦值的是匿名函數,而且是在賦值的時候產生的,也就是說每次渲染都會產生一個新的函數,這就是問題所在。
如果要傳遞的prop很多呢?
恩~~用React-Redux的話,有對shouldComponentUpdate的預設實作。
3. 對多個React元件的效能最佳化
#當一個React元件被裝載、更新和卸載時,元件的一個序列生命週期函數會被呼叫。不過,這些生命週期函數是針對一個特定的React元件函數,在一個應用程式中,從上而下有許多React元件組合起來,它們之間的渲染過程要更加複雜。
同樣一個元件的渲染過程也要考慮三個流程:裝載階段、更新階段、卸載階段
對於裝載階段,元件無論如何都要徹底渲染一次,從這個React元件往下的所有子元件,都要經歷一遍React元件的裝載生命
週期,所以並沒有太多優化的事情可做。
對於卸載階段,只有一個生命週期函數componentWillUnmount,這個函數只是清理componentDidMount新增的事件處理監聽等收尾工作,所以,也沒有什麼可優化的空間;
4. React更新階段的調和(Reconciliation)過程
在元件更新過程,會建立更新Virtual DOM,並將其與先前的Virtual DOM進行比較,從而找出不同之處,使用最少的DOM操作進行更新
調和過程:即React更新中對Virtual DOM找不同的過程,通常對比兩個N個節點的樹形結構的演算法,時間複雜度是O(n*3),如果直接
使用預設對比,節點過多的話,需要操作的數量太多,而React不可能採用這種演算法;
React實際採用的演算法時間複雜度是O(N)(時間複雜度只是對一個演算法最好和最差情況下需要的指令操作數量級的估量)
React的Reconciliation演算法並不複雜,首先檢查兩個樹狀圖的根節點的類型是否相同,根據相同或不同有不同的處理方式:
##節點類型不同的情況
如果树形节点的类型不相同,那就意味着改动很大,直接认为原来的那个树形结构已经没用,可以扔掉,需要从新构建DOM树,原有的树形上的React组件便会经历“卸载”的生命周期;
也就是说,对于Virtual DOM树这是一个“更新”过程,但是却可能引发这个树结构上某些组件的“装载”和“卸载”过程
如:
更新前
<p> <Todos /> </p>
我们想要更新成这样:
<span> <Todos /> </span>
>1. 那么在作比较的时候,一看根节点原来是p,新的是span,类型就不一样了,那么这个算法就废弃之前的p包括里面的所有子节点,从新构建一个span节点和子节点;
>2. 很明显因为根节点不同就将所有的子节点从新构建,这很浪费,但是为了避免O(N*3)的时间复杂度,React这能选择这种比较简单、快捷的方法;
>3. 所以,作为开发者,我们一定要避免上面的浪费的情景出现
节点类型相同的情况
如果两个节点类型相同时,对于DOM元素,React会保留节点对应的DOM元素,只对其节点的属性和内容做对比,然后只修改更新的部分;
节点类型相同时,对于React组件类型,React做得是根据新节点的props去更新节点的组件实例,引发组件的更新过程;
在处理完根节点对比后,React的算法会对根节点的每一个子节点重复一样的操作
多个相同子组件的情况
如果最初组件状态为:
<ul> <TodoItem text = "First" /> <TodoItem text = "Second" /> </ul>
更新后为:
<ul> <TodoItem text = "First" /> <TodoItem text = "Second" /> <TodoItem text = "Third" /> </ul>
那么React会创建一个新的TodoItem组件实例,而前两个则进行正常的更新过程但是,如果更新后为:
<ul> <TodoItem text = "Zero" /> <TodoItem text = "First" /> <TodoItem text = "Second" /> </ul>
(这将暴露一个问题)理想处理方式是,创建一个新的TodoItem组件实例放在第一位,后两个进入自然更新过程
但是要让react按照这种方式,就必须找两个子组件的不同之处,而现有计算两个序列差异的算法时间是O(N*2),显然则
不适合对性能要求很高的场景,所以React选择了一个看起来很傻的办法,即挨个比较每个子组件;
React首先认为把text为First的组件的text改为Zero,Second的改为First,最后创建一个text为Second的组件,这样便会破原有的两个组件完成一个更新过程,并创建一个text为Second的新组件
这显然是一个浪费,React也意到,并提供了方克服,不过需要开发人员提供一点帮助,这就是key
Key的使用
key属性可以明确的告诉React每个组件的唯一标识
如果最初组件状态为:
<ul> <TodoItem key={1} text = "First" /> <TodoItem key={2} text = "Second" /> </ul>
更新后为:
<ul> <TodoItem key={0} text = "Zero" /> <TodoItem key={1} text = "First" /> <TodoItem key={2} text = "Second" /> </ul>
因为有唯一标识key,React可以根据key值,知道现在的第二和第三个组件就是之前的第一和第二个,便用原来的props启动更新过程,这样shouldComponentUpdate就会发生作用,避免无谓的更新;
注意:因为作为组件的唯一标识,所以key必须唯一,且不可变
下面的代码是错误的例子:
<ul> todos.map((item,index) => { <TodoItem key={index} text={item.text} /> }) </ul>
使用数组下标作为key值,看起来唯一,但不稳定,因为随着todos数组值的不同,同样一个组件实例在不同的更新过程中数组的下标完全可能不同,把下标当做可以就会让React乱套,记住key不仅要唯一还要确保稳定不可变
需要注意:虽然key是一个prop,但是接受key的组件不能读取key的值,因为key和ref是React保留的两个特殊prop,并没有预期让组将直接访问。
相关推荐:
以上是React元件的效能優化方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

字體大小的設定成為了重要的個人化需求,隨著手機成為人們日常生活的重要工具。以滿足不同使用者的需求、本文將介紹如何透過簡單的操作,提升手機使用體驗,調整手機字體大小。為什麼需要調整手機字體大小-調整字體大小可以使文字更清晰易讀-適合不同年齡段用戶的閱讀需求-方便視力不佳的用戶使用手機系統自帶字體大小設置功能-如何進入系統設置界面-在在設定介面中找到並進入"顯示"選項-找到"字體大小"選項並進行調整第三方應用調整字體大小-下載並安裝支援字體大小調整的應用程式-開啟應用程式並進入相關設定介面-根據個人

時間複雜度衡量演算法執行時間與輸入規模的關係。降低C++程式時間複雜度的技巧包括:選擇合適的容器(如vector、list)以最佳化資料儲存和管理。利用高效演算法(如快速排序)以減少計算時間。消除多重運算以減少重複計算。利用條件分支以避免不必要的計算。透過使用更快的演算法(如二分搜尋)來優化線性搜尋。

Java框架與React框架的整合:步驟:設定後端Java框架。建立專案結構。配置建置工具。建立React應用程式。編寫RESTAPI端點。配置通訊機制。實戰案例(SpringBoot+React):Java程式碼:定義RESTfulAPI控制器。 React程式碼:取得並顯示API回傳的資料。

手機膜成為了必不可少的配件之一,隨著智慧型手機的普及。延長其使用壽命,選擇合適的手機膜可以保護手機螢幕。幫助讀者選出最適合自己的手機膜、本文將介紹選購手機膜的幾個重點與技巧。了解手機膜的材質及類型PET膜,TPU等、手機膜有多種材質,包括強化玻璃。 PET膜較為柔軟、強化玻璃膜具有較好的耐刮花性能,TPU則具有較好的防震性能。可根據個人偏好及需求來決定,在選擇時。考慮螢幕的保護程度不同類型的手機膜對螢幕的保護程度不同。 PET膜則主要起防刮花作用,強化玻璃膜具有較好的耐摔性能。可以選擇具有較好

Vue.js適合中小型項目和快速迭代,React適用於大型複雜應用。 1)Vue.js易於上手,適用於團隊經驗不足或項目規模較小的情況。 2)React的生態系統更豐富,適合有高性能需求和復雜功能需求的項目。

我們常常會遇到忘記密碼或輸錯密碼而無法解鎖手機的尷尬局面,在使用手機過程中。讓我們重新獲得手機的使用權,而PUK解鎖技巧能夠幫助我們輕鬆解決這些問題。並提供一些實用的技巧,幫助讀者更好地應對手機鎖定畫面問題、本文將以教你PUK解鎖最簡單方法為主題,為大家介紹PUK解鎖的基本概念和步驟。段落1.什麼是PUK解鎖? PUK碼是手機卡上的一個特殊碼,PUK解鎖是一種用於解決手機鎖定螢幕問題的技術,用於解除SIM卡的PIN碼鎖定。了解PUK解鎖的基本概念是學習這項技巧的第一步。 2.如何取得PUK碼?手機螢幕會顯示

React通過JSX與HTML結合,提升用戶體驗。 1)JSX嵌入HTML,使開發更直觀。 2)虛擬DOM機制優化性能,減少DOM操作。 3)組件化管理UI,提高可維護性。 4)狀態管理和事件處理增強交互性。

電腦檔案已經成為了工作和生活中不可或缺的一部分、在數位時代。有時我們可能會不小心刪除或遺失了一些重要的文件,而且還過了七天,以至於無法透過簡單的回收站恢復、然而。我們該如何恢復超過七天失效的文件呢、面對這種情況?本文將為您提供一些實用的方法和技巧。 1.使用文件恢復軟體使用專業的文件恢復軟體是恢復超過七天失效文件的最常見和有效的方法之一。搜尋並還原已刪除或遺失的文件,這些軟體可以掃描儲存設備。 2.利用文件歷史版本功能可以恢復甚至是替換被刪除或遺失的文件,某些作業系統(如Windows)提供了文
