iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0

每次我們呼叫render(),都可以當成建立了一棵樹狀結構,而每一次有 state 或 props 更新時,render() 函式就會回傳一顆不同的 tree。當組件的狀態發生變化時,React 必須計算是否需要更新 DOM。它通過創建一個虛擬DOM 並將其與當前 DOM 進行比較來做到這一點。所以如何最有效率地把舊的樹更新成新的樹就是一件很重要的事了
提到效率,驗算法就是不可或缺的,但即使是目前最先進的演算法都還需要 O(n3) 的時間複雜度,也就是說 1000 個 element 需要 10 億次的比較。

Diffing演算法
當使用這個演算法時,他會從兩棵樹的根開始比較,如果兩棵樹的根不同類型的話,使用的處理方式也會不一樣,若不同類型的話,react會拆掉整棵樹,並且重建,並且舊的dom會被摧毀,同樣的當建立新的樹的時候,新的dom節點也會被加入到dom中,且會執行 UNSAFE_componentWillMount() 與 componentDidMount() 方法,讓state與舊tree失去關聯。

<div>
  <reader />
</div>

<span>
  <reader />
</span>

根據上面提到,react會雖毀舊的reader,並建立一個新的。

如果是同類型dom element的話,react會保留dom節點

<div className="before" title="stuff" />

<div className="after" title="stuff" />

例如這個範例,兩行程式碼中只有className不一樣,所以,react只需要改變 DOM 節點上的className就好。

<div style={{color: 'white', fontWeight: 'bold'}} />

<div style={{color: 'yellow', fontWeight: 'bold'}} />

同樣的,只需要更新不一樣的地方也就是color,不需修改 fontWeight。

Keys
React 提供了 key 屬性。當 children 擁有 key 屬性時,react可以使用key來配對同樣擁有key的children,例如

<ul>
  <li key="2015">morris</li>
  <li key="2016">japan</li>
</ul>

<ul>
  <li key="2014">it home</li>
  <li key="2015">morris</li>
  <li key="2016">japan</li>
</ul>

這時候react就可以知道有著2014key的那個是新的dom,而擁有2015、2016key的則只不過是調換位置而已,你也可以使用元素在 array 中的索引值作為 key。這但如果有順序修改,diff 就會變得比較慢。
可能遇到的問題:

  1. 由於 component instance 會藉由key來決定是否更新或重複使用,如果 key 是一個索引值,那麼修改順序時會修改目前的 key,導致 component 的 state可能相互篡改導致無法預期的變動。
  2. diffing演算法不會嘗試匹配不同 component 類型的 subtree。如果你的不同component輸出內容卻相同的話,建議改成同一類型,較不容易出問題。
  3. 不穩定的 key 會導致許多 component instance 和 DOM 節點被不必要地重新建立,這樣會造成效能的損失以及速度變慢。

參考連結
https://zh-hant.reactjs.org/docs/reconciliation.html
https://www.geeksforgeeks.org/reactjs-reconciliation/


上一篇
[DAY24]Protal是甚麼?
下一篇
[DAY26]什麼是React HOC?
系列文
進階前端網頁設計-初心者的30天React學習及應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言