學習Redux之分析Redux核心代碼分析

  1. React,Flux簡單介紹

  學習React咱們知道,React自帶View和Controller庫,所以,實現過程當中不須要其餘任何庫,也能夠獨立開發應用。可是,隨着應用程序規模的增大,其須要控制的state也會愈來愈多,爲了統一控制,咱們通常都會將全部的狀態和控制邏輯都放在頂層組件中,這樣就會致使,react頂層組件中體積龐大,而且數據和組件混合在一塊兒,很是不方便管理。前端

  在這種狀況下Flux,就出現了,他提出了將應用程序,分爲三部分:dispatcher storeview。其中,dispatcher負責分發事件;store負責保存數據,同時響應事件並更新數據;view負責訂閱store中的數據,根據數據渲染相應的頁面,並提供用戶交互。react

  實際上來講,從React到Flux,咱們只是將咱們React中定義的頂層組件中數據與邏輯拆分到不一樣的文件中:數組

  1. 將state寫在store中,在store 中存放數據,並向外提供一個getter接口,爲state提供惟一數據接口;並建立change事件註冊函數;架構

  2. 將合成事件的回調函數,轉化成action對象(js對象,具備一個type屬性,用於表示action的類型,並經過payload屬性傳遞數據),並使用Dispatcher對象中的dispatch方法將事件對象分發出去。app

  3. 利用dispatcher對象中提供的register方法,註冊action,接收dispatch方法分發action對象,對store的數據進行相應操做,並觸發change事件;框架

  4. 咱們在組件中監聽自定義change事件,當監聽到change事件,從新獲取store中的數據 ,設置state,從新渲染頁面。函數

  實際上Flux並非一個框架,而是前端應用架構,它提出了單向數據流,能夠提供清晰的數據流。同時將數據和組件分離,使應用程序結構更清晰。可是flux依舊存在一些問題。學習

  Redux,利用Flux提出的架構思想和少許的核心代碼,方便了咱們的開發。以上都是簡單介紹,下面經過Redux核心代碼,其中部分都是簡化代碼。spa

  2. Redux核心代碼介紹

  1. createStore方法

  下面代碼是createStore的簡單實現,其中保留了其中三個主要的方法getState,dispatch,subscribe實現,省略了參數處理部分,和一些其餘方法實現。code

// createStore方法簡單實現

const createStore = (reducer) => {

  // 定義state,監聽器數組   let state;   let listeners
= [];   
  // 定義getter方法,惟一一個獲取數據的接口   const getState
= () => state;
  // 定義dispatch方法,用戶分發action事件,接收一個action對象,生成新的state,並通知全部監聽器   const dispatch
= (action) => {
    // 利用reducer生成新的state     state
= reducer(state, action);
    // 通知全部監聽器,調用回調函數     listeners.forEach(listener
=> listener());   };   
  // 定義subscribe方法,註冊監聽器,並返回一個用於取消當前註冊監聽器的函數,用於取消監聽 
  const subscribe
= (listener) => {
    // 添加到監聽數組中     listeners.push(listener);
    // 返回取消監聽函數     
return () => {       listeners = listeners.filter(l => l !== listener);     }   };
  // 調用dispatch,初始化state   dispatch({});
  // 返回getState,dispatch,subscribe三個方法
  return { getState, dispatch, subscribe }; };

  咱們從上面代碼能夠知道,createStore接收一個reducer函數參數,每次調用dispatch函數,利用reducer函數,以及以前的state,以及action,計算出最新的state,並通知全部的監聽器,經過調用getState方法,調用最新的state。同時組件經過subscribe函數,註冊一個監聽器,從而每當數據更新時,通知監聽組件。

  以上就是Redux中最主要的createStore對象中主要方法介紹。

  2. combineReducers函數

  reducer函數,其實就是根據當前的state和action,計算出一個新的state,之因此叫reducer,是由於它的功能就是action對象數組調用reduce函數,產生最新的狀態。

  當咱們的應用程序規模很是大時,咱們須要將reducer進行拆分,咱們能夠直接自定義一個總的合併reducer,也可使用conbineReducers函數來合併,最終效果等價。

// 合併多個reducer
// 返回一個合併的reducer函數,接收兩個參數state和action
/**
 * combineReducers調用方法
 * combineReducers({
 *     a: a,
 *     b: b,
 *     c: c
 * }); 
 * 等價於
 * {
 *     a: a(state.a, action),
 *     b: b(state.b, action),
 *     c: c(state.c, action)
 * }
 */
const combineReducers = reducers => {
    return (state = {}, action) => {
        // 獲取全部自身可枚舉屬性,並進行reduce操做,
        // 將合併在一塊兒,初始值爲空數組
        return Object.keys(reduers).reduce(
            (nextState, key) => {
                nextState[key] = reducers[key](state[key], action);
                return nextState;
            }, {}
        );
    };
};

  3. applyMiddleware函數

  該函數是在當createStore函數傳入applyMiddleware參數時,在createStore中調用的。其實createStore函數的實際參數有三個reducer, preloadedState(state默認值), enhancer, 而且在函數中一些了參數判斷,主要就是,將enhancer(在這裏是applyMiddleware函數) 參數進行匹配,若是createStore參數中具備enhancer, 則直接調用enhancer(createStore)(reducer, preloadedState)對store進行初始化。

  其中applyMiddleware中有調用createStore函數,來初始化store,而後用middleware對初始化的store 中的dispatch函數進行包裝,獲得最終加強的applyMiddleware,最終返回具備加強的applyMiddleware的store。

// 將中間件和store.dispatch組合
// 返回具備整合後的dispatch方法的store

/**/

export default function applyMiddleware(...middlewares) {
    return (createStore) => (reducer, preloadedState, enhancer) => {
        // 根據上面分析,reducer,preloadedState即爲createStore中的reducer,preloadedState
        // enhancer爲空
        
        // 建立一個初始化的store,基本邏輯即爲上面createStore函數分析
        var store = createStore(reducer, preloadedState, enhancer);
        // 獲取此時dispatch函數副本
        var dispatch = store.dispatch;
        // 用於存放中間件函數數組
        var chain = [];

        // 中間件的執行參數,中間件編寫規定
        var middlewareAPI = {
            getState: store.getState,
            dispatch: (action) => dispatch(action)
        };

        // 對每個中間件進行處理後存放
        chain = middlewares.map(middleware => middleware(middlewareAPI));
        // 使用compose函數,將處理後的中間件,和dispatch進行合併,獲得加強後的dispatch
        // 若是chain爲[f1, f2, f3],那麼dispatch通過compose處理後爲 f1(f2(f3(dispatch)))
        dispatch = compose(...chain)(store.dispatch);

        // 將加強後的dispatch,賦值給store,並返回store
        return {...store,
            dispatch
        }
    }
}

  其中的compose函數,主要就是利用了reduceRight函數對參入的參數進行了處理,就不詳細說明了。

  我想你們若是瞭解了上面這些,就能容易理解Redux如何工做的了。

相關文章
相關標籤/搜索