React學習之進階調解器(十八)
React
提供給我們宣告式的API
以至於我們根本不需要關心React
內部到底做了什麼,這讓我們寫程式碼變得輕鬆,但是我們還是非常有必要了解React
內部實現機制,這對我們自己開發一個公司框架以及深入學習React
是非常有幫助的。
這一篇部落格就是深入的講解
React
的更新機制也屬於React的調解器知識點,開啟你內心世界React
的大門,讓我們見識見識diff
演算法的魅力吧,騷年們!
1.演算法魅力
之前將效能優化的時候已經提到過基本的更新流程,render
進行檢視渲染,然後React
檢查是否發生變化,發生了就更新。
有一些一般的演算法以最小的代價更新一棵樹為另外一棵樹,即便是最好的演算法它也是pdf
詳細進行了演算法講解,大家可以去看看,當然在React
高階教程中會進行講解)
當我們在React
用前面那種演算法的話,就單單React
用一個種
這個啟發式演算法的使用基於以下兩點:
只要兩個元素型別不同就會構造出不同的樹
開發者可以會給每一個元素標記一個特殊的雜湊屬性
2.Diff
演算法
型別不同
在比較兩顆樹時,React
首先比較這兩顆樹的根節點,至於判斷不同就是判斷他們的相應的狀態和資料了
如果兩個元素的型別不同的話,React
會拋棄舊的樹,構造新的樹,比如說從<a>
變到了<img>
,<article>
變到了<comment>
,<button>
變到了<div>
,這些變化都會造成一個全新的樹的構建,記住是以當前節點為根,完全重新建立,而不是單單更新根節點。
當摧毀舊樹時,元件會呼叫componentWillUnmount()
進行摧毀自身,當建立新的輸時,會呼叫componentWillMount()
處理,接著就是componentDidMount()
處理,這裡注意componentWillUnmount
和componentWillMount
的區別
這種更新方式會導致子樹的所有節點狀態摧毀,重新進行建立
<div>
<Counter />
</div>
<span>
<Counter />
</span>
型別相同
當型別相同時,React
會看他們的屬性,然後更新要更改的屬性
<div className="before" title="stuff" />
<div className="after" title="stuff" />
這樣,React
只會去修改節點的classNam
e屬性,而不會去更改其他的地方
當處理完這一層節點後,React
就會遞迴去處理它們的子節點
特提:處理型別相同的元件
當是比較型別相同的元件時,React
呼叫componentWillReceiveProps
和componentWillUpdate
函式進行處理(這兩個函式後續會講解),然後直接使用rende
r函式,接著又是diff
演算法處理
3.對於列表孩子的處理
每當他們的父親節點不同時,React
就會處理出孩子列表,然後進行更新。
<ul>
<li>first</li>
<li>second</li>
</ul>
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
當時如果我們只是在孩子節點後面直接插入一個<li>chird</li>
,它只會直接處理。
可是請看下面例子
<ul>
<li>Duke</li>
<li>Villanova</li>
</ul>
<ul>
<li>Connecticut</li>
<li>Duke</li>
<li>Villanova</li>
</ul>
這會更新所有的孩子節點,效率就比較低了
4.keys
優化
為了解決3
最後更新所有孩子節點的問題,React
就提供了一個key
屬性,這個屬性,之前將列表的時候就說過了,維護一個key
比維護一個li
標籤更好。
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
這樣React
直接就知道key=2014
是一個新的元素,而key=2015
和key=2016
則會往後移。
這其中的key
要是唯一的,你可以是物件自己提供的,也可以用陣列的索引,優劣在列表章節已經說了。
5.權衡
瞭解演算法的實現是非常重要的,這樣我們就可以更加深入的瞭解React
處理的每一個細節,從而可以去優化效能.
當然,處理事件的時候一般會遇到這麼兩個問題
如果兩者相似,應該作為不同處理,構造出不同的樹
key
值要具有唯一性,否則會造成子元件的丟失
這兩個就是上面說的啟發式處理的前提條件。
下一篇將講
React
中的資料