Redux is a predictable state container for JavaScript apps.
簡(jiǎn)單的說(shuō)就是Redux能夠管理js app的狀態(tài)飞盆,狀態(tài)是由數(shù)據(jù)維護(hù)的滑燃,也就是說(shuō)Redux是管理數(shù)據(jù)的。那么Redux是怎么管理數(shù)據(jù)的呢疆液?
store
一個(gè)Redux app中只有一個(gè)store一铅,所有的數(shù)據(jù)都在這個(gè)store中,而通過(guò)createStore(reducer, [initState])
枚粘,initState是可選參數(shù)馅闽,也就是說(shuō)決定store的是reducer,reducer決定store中存放什么樣的數(shù)據(jù)馍迄、處理什么樣的數(shù)據(jù)福也、處理數(shù)據(jù)的方式。
store在創(chuàng)建的時(shí)候內(nèi)部會(huì)執(zhí)行dispatch({ type: ActionTypes.INIT })
攀圈,用來(lái)初始化整個(gè)store的數(shù)據(jù)結(jié)構(gòu)暴凑,同時(shí)獲取reducer中的默認(rèn)數(shù)據(jù)。之所以能拿到全部的數(shù)據(jù)結(jié)構(gòu)赘来,是因?yàn)樵?code>dispatch({ type: ActionTypes.INIT })的時(shí)候现喳,所有的reducer都會(huì)執(zhí)行凯傲,并根據(jù)reducer的combine結(jié)構(gòu)生成數(shù)據(jù)。在Redux內(nèi)嗦篱,每執(zhí)行一次dispatch冰单,所有的reducer都會(huì)執(zhí)行。
reducer
所以這里就有個(gè)問(wèn)題灸促,如果reducer比較多的時(shí)候诫欠,性能是不是就會(huì)出問(wèn)題。大家可能會(huì)想到減少reducer浴栽,這也是一個(gè)辦法荒叼,但是如果刻意減少reducer的話,可能會(huì)導(dǎo)致某個(gè)reducer內(nèi)過(guò)于復(fù)雜典鸡,后期難以維護(hù)被廓。
const dispatcher = (state={}, action) {
switch (action.type) {
case "TYPE1":
case "TYPE2":
return reducerFirst(state, action)
case "TYPE3":
return reducerSecond(state, action)
default:
return state
}
}
通過(guò)這樣簡(jiǎn)單的過(guò)濾就可以實(shí)現(xiàn)只讓對(duì)action感興趣的reducer執(zhí)行,簡(jiǎn)單萝玷,方便嫁乘,快捷。
action
action是個(gè)object间护,它必須有個(gè)type屬性亦渗,一般是個(gè)常量挖诸,來(lái)標(biāo)示action類(lèi)型汁尺,方便reducer處理。除去type剩下的一般就是要處理的數(shù)據(jù)多律,如果數(shù)據(jù)比較簡(jiǎn)單可以直接使用Object.assign({}, state, action.data)
來(lái)處理痴突,這種方法僅適合簡(jiǎn)單數(shù)據(jù)。
如果是復(fù)雜數(shù)據(jù)狼荞,有較深的層級(jí)辽装,就要使用深度拷貝,這時(shí)候你可以使用lodash的cloneDeep進(jìn)行深度拷貝相味。
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// ? false
immutable
但是復(fù)雜數(shù)據(jù)的深度拷貝是很花性能的拾积,這個(gè)時(shí)候就可以使用immutable.js來(lái)解決這個(gè)問(wèn)題。immutable不可改變的意思丰涉,在Object-C中是原生提供這種數(shù)據(jù)類(lèi)型的拓巧。對(duì)immutable.js生成的數(shù)據(jù)進(jìn)行操作之后總是返回一個(gè)新的數(shù)據(jù),原有的數(shù)據(jù)不會(huì)改變一死。
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通過(guò)結(jié)構(gòu)共享來(lái)解決的數(shù)據(jù)拷貝時(shí)的性能問(wèn)題肛度,數(shù)據(jù)被set的時(shí)候,immutable.js會(huì)只clone它的父級(jí)別以上的部分投慈,其他保持不變承耿,這樣大家可以共享同樣的部分冠骄,可以大大提高性能。如圖
subscribe
每次執(zhí)行dispatch加袋,通過(guò)subscribe注冊(cè)的listener都會(huì)被執(zhí)行凛辣,如果listener較多,或者listener內(nèi)部處理比較復(fù)雜也會(huì)對(duì)性能產(chǎn)生影響职烧, 而且在listener內(nèi)部很難區(qū)分哪個(gè)數(shù)據(jù)被改變了蟀给,如果在listener內(nèi)部繼續(xù)dispatch,而沒(méi)有處理好執(zhí)行dispatch條件的話阳堕,很容易造成dispatch->listener->dispatch死循環(huán)跋理。所以建議通過(guò)middleware的方式來(lái)處理,而且在middleware內(nèi)部可以知道action是什么恬总,就可以只處理關(guān)心的action前普。
總結(jié)
預(yù)分配reducer、精簡(jiǎn)reducer
精簡(jiǎn)action數(shù)據(jù)或使用immutable.js
使用middleware處理特殊需求(reducer中不方便處理的需求)