使用方式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方法