React
在Web開發中,要将更新的資料實時反映到UI上,就不可避免地需要對DOM進行操作,而複雜頻繁的DOM操作通常是産生性能瓶頸的原因之一。為此,React引入了
Virtual DOM
機制。
Virtual DOM
實際上是在浏覽器端用
JavaScript
實作的一套
DOM API
,它包括:
-
模型Virtual DOM
- 生命周期的維護和管理
- 性能高效的diff算法
- 将
展示為原生DOM的Virtual DOM
方法Patch
基于React進行開發時,所有的DOM樹都是在
Virtual DOM
的基礎上構造的。React在
Virtual DOM
上實作了
DOM diff
算法,當資料更新時,會通過diff算法尋找到需要變更的DOM節點,并隻對變化的部分進行實際的浏覽器的DOM更新,而不是重新渲染整個DOM樹。
Virtual DOM
模型
Virtual DOM
ReactNode
- ReactElement
- ReactComponentElement
- ReactDOMElement
- ReactFragment
- ReactText
建立React元素
通過JSX建立的虛拟元素最終會被編譯成調用React的
createElement
方法
初始化元件入口
當使用React建立元件時,首先會調用
instantiateReactComponent
,這是初始化元件的入口函數,它通過判斷node類型來區分不同元件的入口
文本元件
ReactDOMTextComponent
标簽元件
ReactDOMComponent
自定義元件
ReactCompositeComponent
生命周期
React的主要思想是通過建構可複用元件來建構使用者界面。所謂元件,就是有限狀态機,通過狀态渲染對應頁面,每個元件元件都有自己的生命周期,它規定了元件和方法需要在哪個階段改變和執行。
diff算法
diff算法會幫助我們計算出
Virtual DOM
中真正變化的部分,并隻針對該部分進行原生DOM操作,而非重新渲染整個頁面,進而保證了每次操作更新後頁面的高效渲染。
傳統diff算法
- 計算一顆樹形結構轉換成另一棵樹形結構的最少操作
- 傳統算法通過循環遞歸對節點進行一次對比,算法複雜度達到O(n³)
React對diff算法的改進
React結合DOM樹的特點,對傳統diff算法進行了改進,将其轉換為O(n)複雜度的問題
React diff算法的三個政策
- Web UI中DOM節點跨層級的操作較少(如果有,可以了解為删去一個節點,在另一層級插入新節點)
- 擁有相同類的兩個元件會生成相似的樹形結構,擁有不同類的兩個元件将會生成不同的樹形結構
- 對于同一層級的一組子節點,它們可以通過唯一的id進行區分
tree diff(上面的第一個政策)
- 對樹進行分層比較,兩顆樹隻會對同一層次的節點進行比較
- React隻會簡單地考慮同層級節點的位置變換,而對于不同層級的節點,隻有建立和删除操作
- 在開發元件時,保持穩定的DOM結構有助于性能的提升,建議不要進行DOM節點跨層級的操作
component diff(第二個政策)
- 如果是同一類型的元件,則按照原政策繼續比較Virtual DOM
- 如果不是同一類型的元件,則将舊元件直接删除,在該位置重新建立新元件
- 如果是同一類型的元件,有可能其Virtual DOM沒有任何變化,如果我們能夠明确知道這點,這可以利用shouldComponentUpdate()來判斷元件是否需要進行diff算法分析
element diff(第三個政策)
- 當節點處于同一層級時,diff算法提供了3中節點操作,分别為插入、移動、删除
- 對于同一層級的同組子節點,需要添加唯一key進行區分,通過這種方法來解決相同節點位置變化的情況
React Patch方法
将diff算法計算出來的DOM差異隊列更新到真實的DOM節點上,最終讓浏覽器能夠渲染出更新的資料。
(未完待續...)
參考
深入淺出React