在Redux源碼中主要有四個文件createStore,applyMiddleware,bindActionCreators,combineRedures createStore.js export default function createStore(reducer, preloadedSta ...
在Redux源碼中主要有四個文件createStore,applyMiddleware,bindActionCreators,combineRedures
createStore.js
export default function createStore(reducer, preloadedState, enhancer),其中reducer函數是用來計算規則,preloadedState是初始狀態,enhancer(高階組合函數)是用來增強store對象,返回增強後的store createStore將通過閉包的方式,封裝私有變數,該store中的state等狀態會被保存 //返回 store 暴漏出的介面return { dispatch, //唯一一個可以改變 state 的哈按時 subscribe, //訂閱一個狀態改變後,要觸發的監聽函數 getState, // 獲取 store 里的 state replaceReducer, //Redux熱載入的時候可以替換 Reducer [$$observable]: observable //對象的私有屬性,供內部使用 }如果preloadedState 是function,而enhancer為null,那麼將兩者交換,enhancer必須是function
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') { enhancer = preloadedState // 把 preloadedState 賦值給 enhancer preloadedState = undefined // 把 preloadedState 賦值為 undefined }function subscribe(listener)主要通過觀察者模式返回一個取消訂閱的函數,訂閱通過一個數組隊列來完成,添加或者取消監聽之前都會保存一份訂閱快照 在function dispatch(action)中, //標記 dispatch 正在運行 isDispatching = true //執行當前 Reducer 函數返回新的 state currentState = currentReducer(currentState, action) 然後對所有的訂閱數組隊列,進行遍歷
//所有的的監聽函數賦值給 listeners var listeners = currentListeners = nextListeners //遍歷所有的監聽函數 for (var i = 0; i < listeners.length; i++) { // 執行每一個監聽函數 listeners[i]()
applyMiddleware
return一個函數,它可以接受createStore方法作為參數,給返回的store的dispatch方法再進行一次包裝return function (reducer, preloadedState, enhancer) { var store = createStore(reducer, preloadedState, enhancer); var _dispatch = store.dispatch; //獲取dispatch var chain = []; var middlewareAPI = { getState: store.getState, dispatch: function dispatch(action) { return _dispatch(action); } }; chain = middlewares.map(function (middleware) { //遍歷middlewares綁定 return middleware(middlewareAPI); }); _dispatch = compose.apply(undefined, chain)(store.dispatch); return _extends({}, store, { dispatch: _dispatch }); };
bindActionCreators
將action和dispatch綁定起來: bindActionCreators(actionCreators, dispatch)// 判斷 actionCreators 是一個函數 if (typeof actionCreators === 'function') { // 調用 bindActionCreator , 返回包裝後的 actionCreators , 包裝後 actionCreators 可以直接 dispath return bindActionCreator(actionCreators, dispatch); } 如果是Object對象的話,遍歷Object的key,獲取Oobject每個key對應的value // 獲取 actionCreators 所有的 key var keys = Object.keys(actionCreators); // 用來保存新 轉換後的 actionCreators var boundActionCreators = {}; // 遍歷 所有的 actionCreators keys for (var i = 0; i < keys.length; i++) { var key = keys[i]; // 獲取當前的 actionCreator var actionCreator = actionCreators[key]; // 當前的 actionCreator 是一個函數 if (typeof actionCreator === 'function') { // 調用 bindActionCreator , 返回包裝後的 actionCreators , 包裝後 actionCreators 可以直接 dispath boundActionCreators[key] = bindActionCreator(actionCreator, dispatch); }
combineReducers
獲取combineReduces傳進來的對象,獲取對象的所有key集合finalReducerKeys。<Provider store={store}> </Provider>獲取state集合,遍歷reducers集合找到當前reducers中的state,然後和經過reducer後的獲取的新的state做對比,如果發生改變返回state
//迴圈遍歷 finalReducerKeys ,執行所有的 reducer, 所以大家一定不要有相同的 action.type ,否則你的狀態一定會混亂的 for (var i = 0; i < finalReducerKeys.length; i++) { //獲取當前的 key var key = finalReducerKeys[i] //獲取當前 reducer var reducer = finalReducers[key] //獲取當前 key 的 state var previousStateForKey = state[key] //執行 reducer ,獲取 state var nextStateForKey = reducer(previousStateForKey, action) //判斷執行完Reducer後, 返回回來的 nextStateForKey 是 undefined if (typeof nextStateForKey === 'undefined') { //得到 Undefined 狀態的錯誤消息 var errorMessage = getUndefinedStateErrorMessage(key, action) //拋出異常 throw new Error(errorMessage) } //賦值給 nextState nextState[key] = nextStateForKey //判斷 state 是否經過 Reducer 改變了 hasChanged = hasChanged || nextStateForKey !== previousStateForKey } //返回state return hasChanged ? nextState : state