Redux性能優(yōu)化

Redux is a predictable state container for JavaScript apps.

簡單的說就是Redux能夠管理js app的狀態(tài),狀態(tài)是由數(shù)據(jù)維護的,也就是說Redux是管理數(shù)據(jù)的。那么Redux是怎么管理數(shù)據(jù)的呢?

store

一個Redux app中只有一個store,所有的數(shù)據(jù)都在這個store中,而通過createStore(reducer, [initState]),initState是可選參數(shù),也就是說決定store的是reducer,reducer決定store中存放什么樣的數(shù)據(jù)、處理什么樣的數(shù)據(jù)、處理數(shù)據(jù)的方式。
store在創(chuàng)建的時候內(nèi)部會執(zhí)行dispatch({ type: ActionTypes.INIT }),用來初始化整個store的數(shù)據(jù)結(jié)構(gòu),同時獲取reducer中的默認數(shù)據(jù)。之所以能拿到全部的數(shù)據(jù)結(jié)構(gòu),是因為在dispatch({ type: ActionTypes.INIT })的時候,所有的reducer都會執(zhí)行,并根據(jù)reducer的combine結(jié)構(gòu)生成數(shù)據(jù)。在Redux內(nèi),每執(zhí)行一次dispatch,所有的reducer都會執(zhí)行。

reducer

所以這里就有個問題,如果reducer比較多的時候,性能是不是就會出問題。大家可能會想到減少reducer,這也是一個辦法,但是如果刻意減少reducer的話,可能會導(dǎo)致某個reducer內(nèi)過于復(fù)雜,后期難以維護。

const dispatcher = (state={}, action) {
  switch (action.type) {
    case "TYPE1": 
    case "TYPE2":
      return reducerFirst(state, action)
    case "TYPE3":
      return reducerSecond(state, action)
    default:
      return state
  }
}

通過這樣簡單的過濾就可以實現(xiàn)只讓對action感興趣的reducer執(zhí)行,簡單,方便,快捷。

action

action是個object,它必須有個type屬性,一般是個常量,來標示action類型,方便reducer處理。除去type剩下的一般就是要處理的數(shù)據(jù),如果數(shù)據(jù)比較簡單可以直接使用Object.assign({}, state, action.data)來處理,這種方法僅適合簡單數(shù)據(jù)。
如果是復(fù)雜數(shù)據(jù),有較深的層級,就要使用深度拷貝,這時候你可以使用lodashcloneDeep進行深度拷貝。

var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// ? false

immutable

但是復(fù)雜數(shù)據(jù)的深度拷貝是很花性能的,這個時候就可以使用immutable.js來解決這個問題。immutable不可改變的意思,在Object-C中是原生提供這種數(shù)據(jù)類型的。對immutable.js生成的數(shù)據(jù)進行操作之后總是返回一個新的數(shù)據(jù),原有的數(shù)據(jù)不會改變。

var Immutable = require('immutable');
var map1 = Immutable.Map({a:1, b:2, c:3});
var map2 = map1.set('b', 50);
map1.get('b'); // 2
map2.get('b'); // 50

immutable.js通過結(jié)構(gòu)共享來解決的數(shù)據(jù)拷貝時的性能問題,數(shù)據(jù)被set的時候,immutable.js會只clone它的父級別以上的部分,其他保持不變,這樣大家可以共享同樣的部分,可以大大提高性能。如圖

immutable-js-share.gif

subscribe

每次執(zhí)行dispatch,通過subscribe注冊的listener都會被執(zhí)行,如果listener較多,或者listener內(nèi)部處理比較復(fù)雜也會對性能產(chǎn)生影響, 而且在listener內(nèi)部很難區(qū)分哪個數(shù)據(jù)被改變了,如果在listener內(nèi)部繼續(xù)dispatch,而沒有處理好執(zhí)行dispatch條件的話,很容易造成dispatch->listener->dispatch死循環(huán)。所以建議通過middleware的方式來處理,而且在middleware內(nèi)部可以知道action是什么,就可以只處理關(guān)心的action。

總結(jié)

預(yù)分配reducer、精簡reducer

精簡action數(shù)據(jù)或使用immutable.js

使用middleware處理特殊需求(reducer中不方便處理的需求)

參考

Redux

immutable.js

cloneDeep

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容