react 實踐之 redux applyMiddleware方法詳解

使用方式java

const store = applyMiddleware(...middlewares)(createStore)(reducer, initialState)

源碼 版本 0.14.0redux

function applyMiddleware() {
    //1
  for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
  }
  //2
  return function (createStore) {
      //3
    return function (reducer, preloadedState, enhancer) {
      //4
      var store = createStore(reducer, preloadedState, enhancer);
      var _dispatch = store.dispatch;
      var chain = [];
      //5
      var middlewareAPI = {
        getState: store.getState,
        dispatch: function dispatch(action) {
          return _dispatch(action);
        }
      };
      chain = middlewares.map(function (middleware) {
        return middleware(middlewareAPI);
      });
      //6
      _dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch);

      return _extends({}, store, {
        dispatch: _dispatch
      });
    };
  };
}

applyMiddleware方法主要是對redux的dispacth方法進行封裝設計模式

原理數組

const _dispatch = store.dispatch;
store.dispatch = function (action) {
  console.log('加強功能');
  _dispatch(action);
  console.log('加強功能');
}

原理很簡單就是將store的dispatch進行替換,換成一個功能加強了可是具備dispach功能的新函數請輸入代碼
原理和java設計模式中的 裝飾者模式很像,旨在加強功能,但不改變接口app

接下來具體分析 applyMiddleware 函數函數

1. 代碼//1spa

for (var _len = arguments.length, middlewares = Array(_len), _key = 0; _key < _len; _key++) {
    middlewares[_key] = arguments[_key];
}

因爲第一個框號(...middlewares)裏面的參數能夠是多箇中間件(m1,m2,m3)這種類型,或者是一箇中間件數組
因此這裏經過 遍歷 js函數的 arguments 屬性將全部的參數取出放到 middlewares 數組中設計

2. 代碼//2 //3code

applyMiddleware 這個函數實際上是一個 柯里化 的函數,
柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,
而且返回接受餘下的參數且返回結果的新函數的技術中間件

這裏有幾個關鍵字 多個參數 單一參數 返回接受餘下參數的函數 返回結果
//舉例

function count(a,b,c) {
    return a+b+c;
}
count(1,2,3);

咱們看到 count接受多個參數,這裏是三個,最後返回了計算結果,接下來把它柯里化

function count(a) {
    return function(b) {
        return function(c) {
            return a+b+c;
        }
    }
}
count(1)(2)(3);

咱們看到區別在於 柯里化 後函數只接受一個參數,返回了接受剩餘參數的函數,因此要分屢次調用

3. //代碼4

var store = createStore(reducer, preloadedState, enhancer);
var _dispatch = store.dispatch;
var chain = [];

這裏作了三件事情,1 用reducer建立了一個 store,2 var _dispatch = store.dispatch; 將原來的
dispatch方法保存了起來,由於後咱們要覆蓋 dispach 但又要用到原始的dispatch的功能,因此保存
3 var chain = [];咱們的中間件也是一個 柯里化 的函數,這個數組用來保存中間件接受第一個參數
後返回的函數

4. //代碼5

var middlewareAPI = {
    getState: store.getState,
    dispatch: function dispatch(action) {
      return _dispatch(action);
    }
};
chain = middlewares.map(function (middleware) {
    return middleware(middlewareAPI);
});

middlewareAPI 對象有兩個成員 getState和dispatch,因爲這兩個成員咱們會在中間件裏面用到
因此咱們要將它們傳遞給中間件 調用 middlewares.map 方法,middlewares是一個數組,map方法
接受一個函數,這個函數的第一個參數就是 middlewares 數組的成員,咱們調用map方法會遍歷
middlewares數組,將它的每個成員傳遞給 成員處理函數,最終返回了一個由 處理函數返回值
組成的數組,經過以上代碼咱們就能夠在中間件中使用getState,和dispatch這兩個方法了

5. //代碼6

_dispatch = _compose2['default'].apply(undefined, chain)(store.dispatch);
return _extends({}, store, {
        dispatch: _dispatch
});

這裏作的事情就是咱們開始的原理中作的事情 將 disatch 加強而且替換掉store中的dispatch,替換後的dispach中會調用中間件,咱們看到返回值_extends 是一個函數,接收store,和加強後的_dispatch,用來替換本身的 dispatch方法

相關文章
相關標籤/搜索