之前畫了一張redux的流程圖,可以看看右下角的部分,可以看出來怎麼進行優化。
在reducer裡面,儘量減少資料的變動
不要做多餘、無意義的事
也就是能不改變就不改變。比如不要做下面這種無謂的事情:
function reducer(state, action){
// ....一大堆邏輯程式碼
return {
...state
}
}
這個程式碼雖然在selector中,也可以通過areStatePropsEqual
來判斷計算後的state是否發生了改變。
但是如果直接return state;
就可以直接被areStatesEqual
攔截,避免多餘的計算和對比。
要做多餘的檢查
同樣,state內部資料,如果資料相同,儘量使用原資料。只針對複雜資料型別(Object
, Array
)。
比如:
function reducer(state, action) {
let mayNotChange = state.mayNotChange; // mayNotChange為Array或Object
let newState = {...mayNotChange};
// ...一大堆邏輯
return {
...state,
mayNotChange: changed ? newState : mayNotChange // 沒有發生改變的話,就用原來的物件
}
}
很多時候,一般習慣於通過計算,然後直接把生成的newState
賦值給mayNotChange
。
由於眾所周知的{} !== {}
的情況,如果能通過簡單判斷來決定是否可以選擇使用原來的物件,那麼就可以通過areStatePropsEqual
來進行判斷,同樣可以避免不必要的計算,更可以避免不必要的渲染。
注: 所說的選擇使用原來的物件,是確定資料沒有發生改變的時候,使用原物件。並不是說當發生改變的時候,也在原來的物件上面修改最好。在不考慮自定義areStatesEqual和areStatePropsEqual的情況下,如果只在原物件上面進行修改,可能會造成對比的時候,前後兩種結果相同,可能造成無法重新渲染的情況
優化equal的四個方法
在connect
的option
中,有四個對比的方法
-
areStatesEqual
(預設為===
),用來判斷redux store
返回的state
是否和之前的相同 -
areOwnPropsEqual
(預設為shallowEqual
),用來判斷父元件傳入的props
是否和之前的相同 -
areStatePropsEqual
(預設為shallowEqual
),用來判斷mapStateToProps
的結果是否和之前的相同 -
areMergedPropsEqual
(預設為shallowEqual
),用來判斷最後merge合併的最終結果是否和之前的相同
可以通過自己的需求對著四個方法進行優化。
比如一個redux
的state
是這個樣子:
state = {
pageA: {...},
pageB: {...},
number: 2
}
而在pageA裡面只需要pageA
和number
,那麼就可以通過areStatesEqual
來進行對比:
function areStatesEqual(prev, current){
return prev.number === current.number && isEqual(prev.pageA, current.pageA);
}
或者針對複雜結構資料的情況,進行特殊處理,比如深度對比
function areStatePropsEqual(prev, current){
return deepEqual(prev, current);
}
這些優化都可以減少不必要的計算和重渲染。
shouldComponentUpdate
多餘提一句,在使用shouldComponentUpdate
的時候,要謹慎使用。這個方法就是利用shouldComponentUpdate的消耗來換取render的消耗。
當某些小的、呼叫的次數少的component,就沒有必要新增shouldComponentUpdate檢查。
當元件夠大,夠複雜,可以考慮使用這個方法來減少re-render的消耗。當然,還是需要考慮用這個方法的消耗和diff&render的消耗比起來哪個更划算。
先想到這麼多,等想到了其他的再新增上來。