天天看點

React的Diff算法

使用React或者RN開發APP如果不知道Diff算法的話簡直是說不過去啊。畢竟“知其然,知其是以然”這句老話從遠古喊到現代了。

React的元件在渲染之後組成了一個樹形結構。在React繪制的時候,會在記憶體裡對應每一個元件建立一個節點,并最終形成一個群組件樹結構一樣的樹。我們就叫這個樹叫影子樹(這個叫法不是出自官方)。我們可以了解為這個影子樹包含了React App組建的結構和一些屬性值。

在元件發生變化的時候(一般是調用了<code>setState</code>),React會形成一個影子樹二号。然後對比影子樹1号和影子樹2号的不同。

我們知道對比兩個樹的最小不同的時間複雜度是O(n3

),n是樹裡的節點數。這個複雜度下,稍有量級的應用都會遇到一個問題:無法忽略的慢。于是,FB的同學們使用了更加高效的啟發式算法,把複雜度降低到了O(n)。

但是,不管是什麼算法最後都需要對比兩個節點的不同。有三種情況需要考慮:

節點,英語裡的Node,包括兩種類型:一個是React元件,一個是HTML的DOM。下文也是同樣的含義。

如果是HTML DOM不同的話,直接使用新的替換舊的。

如果是元件類型不同的話也直接使用新的替換舊的。

在React裡樣式并不是一個純粹的字元串,而是一個對象,這樣的話在樣式發生改變的時候隻需要改變替換變化以後的樣式。修改完目前節點之後,遞歸處理該節點的子節點。

元件類型相同的,使用React機制處理。一般是使用新的props替換掉舊的props,并在之後調用元件的<code>componentWill/DidReceiveProps</code>方法,之前的元件的render方法會被調用。節點的比較機制開始遞歸作用于這個它的子節點上。

一列節點中的一個發生了改變,React并沒有什麼好方法來處理這個問題。循環新舊兩個清單,并找出不同是React唯一的處理方法。

但是,有一個可以把這個算法的複雜度降低的辦法。那就是我們在生成一列節點的時候給每一個節點上添加一個key。這個key隻需要在這一列節點中唯一,不需要全局唯一。

需要注意的是,上面的啟發式算法是基于兩點假設:

類型想聽的節點總是生成同樣的樹,而類型不同的節點也總是生成不同的樹。

可以為多次render都表現穩定的節點設定key。

上面的節點之間的比較算法基本就是基于這兩個假設而實作的。也就是要提高React應用的效率,需要我們按照這兩點假設來開發。

否則,React會重獲整個APP。那就是噩夢一樣的情況了。

歡迎加群互相學習,共同進步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,轉載請注明出處!

本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sunshine-anycall/p/5950650.html,如需轉載請自行聯系原作者

繼續閱讀