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方法

相关文章
相关标签/搜索