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

来源:互联网 发布:如何做淘宝排名 编辑:程序博客网 时间:2024/06/07 10:04

谈到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()

    )

  )


0 0