您的位置:首页 > Web前端 > React

React实战-深入源码了解Redux用法之Middleware

2016-12-29 21:39 543 查看
谈到MiddleWare的由来在官方网站有清楚的说明,并且是一步一步的讲解了它的演进过程,其中中文说明见http://cn.redux.js.org/docs/advanced/Middleware.html(微信:react-javascript)。
重点讲解了几点内容:
1.为什么采用MiddleWare?
综合起来看就是我们在进行业务操作时,常常会有其它的附加需求,如:所有操作的操作记录日志;操作异常的错误日志;测试过程的测试类信息等等。
然而我们即不希望改变原有代码,也不希望在有太多重复的代码,所以在Redux中提供了一种简易的方式,将附加操作单独编写,采用appplyMiddleware进行统一封装,将业务操作与附加操作分离。
2.Middleware是怎么实现的?
正如官网分析的一样,我们有多种方法去实现,但是那种方式才是最简单、耦合度最低的呢?
毋庸置疑的是这种情形下最适合采用的就是装饰者模式。也就是保持原有代码不变的情况下,对初始对象进行不断的增加新的数据或操作。
在面向对象的语言中,装饰者模式是一种常见的开发模式,实现的方式有多种,主要采用的是重构和组合的方式:通过继承和组合的方式,定义装饰类,将原有类的对象作为装饰类的内部元素,然后根据需要增加新的数据和操作。
在Javascript中要实现这种方式主要采用的是Mondkeypatching的方式,采用将原有function进行重写,在重写的function中增加新的数据和操作。如:
function A(){
}
A.prototype.add(i,j){
return i+j;
}
Monkeypatching将重写add,并添加日志信息。
var a = new A();
var originalAdd = a.add;
A.add = function(i,j){
console.log(‘begin add’);
return originalAdd(i,j);
}
从上面的代码可以看出基本上是javascript对重构的一种实现。
基本思路如此,但是还有一点需要特别注意的是,为什么不完全采用Monkeypatching。主要原因是Middleware不只有一个,而是多个,这就需要实现dispatch的链式效果,每次封装的后的dispatch将作为后一个Middleware的初始dispatch。
另外我们可以看到在Redux源码中,通过以下代码实现了Middleware的链式链接。
applyMiddleware中:
chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(…chain)(store.dispatch)
compose中:
const last = funcs[funcs.length - 1]
  const rest = funcs.slice(0, -1)
  return (...args) => rest.reduceRight((composed, f) => f(composed), last(…args))。
3.Middleware怎么写?
具体到Middleware怎么写就变的很简单了,在官网的多个例子中,选取最简单的看看吧。
const logger = store => next => action => {
  console.group(action.type)
  console.info('dispatching', action)
  let result = next(action)
  console.log('next state', store.getState())
  console.groupEnd(action.type)
  return result
}
采用的是箭头函数,我们需要了解的是三个嵌套箭头函数的参数:
1.store:全局数据对象
2.next:上一个被封装的dispatch
3.action:操作。
基本上了解这些你就可以编写自己的附加操作了。需要注意的是对next的使用,是要获取结果,还是要进行附加操作,另外就是要将再次封装的next传出去。
在构建store时,也将改为以下代码:
const configureStore = preloadedState => {
  const store = createStore(
    rootReducer,
    preloadedState,
    compose(
      applyMiddleware(thunk, api, createLogger()),
      DevTools.instrument()
    )
  )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息