當 React 元件遇到效能瓶頸時,在重構或解析元件需從 Element、Reconciliation 概念開始了解,React 主要幫我們將狀態轉換成畫面,另外
- 讓開發者用 JavaScript 處理所有事情
- 提供 JSX 支援
- 將邏輯和渲染分開,所以寫一套邏輯可渲染在不同平台
- Reconciliation 跟 render 是不同階段的動作,最佳化算法 (fiber) 也可以套用在不同平台
Element X JSX
元件中的 JSX 會透過 createElement 這個 function 被轉換成 React Element。
React Element 是一個物件,包含 type 及 properties,type 用來區分是 component instance 或是 DOM node,Element 在 React 中又分成兩種
- Element (type 為 DOM node)
1 | { |
- Component Element (type 為 instance)
1 | const DeleteAccount = () => ({ |
Virtual Dom
當我們知道底層的定義之後,要先記住 React 在做的事情:
React.js 就是給狀態然後出畫面
瀏覽器中的畫面是 DOM tree 構成,因為 DOM tree 的操作是成本高的動作,可以參考 state of the art algorithms O(n3),React 效能好就歸功於寫的程式碼並不會操作 DOM,而是會有以下特性:
- 改變的狀態其實是操作我們常聽到的 Virtual Dom
- 狀態對 UI 影響是非同步,如果狀態在一個循環內
A -> B -> C -> A
這樣最後 DOM 就不會變化 - 相同 type,如果 attributes 改變則會偵測並變化 attribute
- Reconciliation (fiber) 將複雜度減少到 O(n)
所以 React 也會這樣的資料結構中,處理狀態對於元件的改變,這個結構就是我們常聽的 Virtual Dom,有篇開箱文寫的很棒:
https://pomb.us/build-your-own-react/
在這篇文章中可以看成是一棵 left-chlid right-sibling tree:
- 每一個 Node 有指向 Parent 的參考
- 過程先看有沒有 Child,再看有沒有 Sibling,都沒有才回到 Parent
- 整棵樹走完才 render 結果到實際的 DOM 上
Reconciliation
Reconciliation 就是一個演算法,找出哪些樹節點哪些需要變化,當我們呼叫 render()
的時候,React 會做一個 Top-Down 的 Reconciliation。
過程中會不停地去問你的 type 是什麼? 如果我們定義了一個 Component Elements X 且 type 是 Y,那 React 就會去問什麼是 Y,直到問到最基礎的組成為止。
Reconciliation 實作上會符合以下假設:
- 不同 type,在 react 會產生不同的樹,不會去偵測而是直接取代
- 偵測一個 list 的改變會透過 keys 來增加效能
1 |
|
校能優化注意事項
- 不要去修改 dom 的 attribute,讓 React 處理
- key 盡量用後端給出來不易重複的值
- setState 是 batch 的非同步動作,所以要注意狀態是 immutable
- 下個狀態與前一個狀態有關的時候,
setState((prveState) => {...prevState, newState})
;
喜歡這篇文章,請幫忙拍拍手喔 🤣