Redux源码解读(二)

上篇文章我们分析了createStore和combineReducers文件,这一篇我们分析剩下的文件。


首先是bindActionCreators文件,这个文件十分简单

function bindActionCreator(actionCreator, dispatch) {
  return function() {
    return dispatch(actionCreator.apply(this, arguments))
  }
}

上面的高阶函数是在文件内部中使用,这个是为了减少重复代码,返回的函数中的参数传给的actionCreator函数执行,然后dispatch将其返回值作为参数再执行,其返回值作为该函数的返回值。

export default function bindActionCreators(actionCreators, dispatch) {
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch)
  }

  if (typeof actionCreators !== 'object' || actionCreators === null) {
    throw new Error(
      `bindActionCreators expected an object or a function, instead received ${
        actionCreators === null ? 'null' : typeof actionCreators
      }. ` +
        `Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?`
    )
  }

  const keys = Object.keys(actionCreators)
  const boundActionCreators = {}
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const actionCreator = actionCreators[key]
    if (typeof actionCreator === 'function') {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
    }
  }
  return boundActionCreators
}

这个函数很简单,其中第一个参数既可以是函数也可以是对象,如果是函数,则直接返回bindActionCreator处理后的函数,若为对象,则通过循环其key值递归找到每一个对应的ActionCreator,最后返回一个相应的对象。

也就是说,如果输入的是函数,则返回的是函数,若输入的是对象,则返回的也是对象。


接下来我们看compose文件(其实这个文件只是一个工具函数)

export default function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }

  if (funcs.length === 1) {
    return funcs[0]
  }

  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}

当compose参数为空时,则返回一个函数,该函数直接返回其参数

若参数为一个时,则直接返回该参数(该参数应当是一个函数)

若参数为多个时,则通过reduce进行累计,返回一个函数,该函数内部是一层一层函数的叠加,该函数参数在叠加的最内层调用。举个栗子��

compose(f, g, h)就意味着
返回(...args) => f(g(h(...args)))

而compose函数在applyMiddleware中被使用

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args)
    let dispatch = () => {
      throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
          `Other middleware would not be applied to this dispatch.`
      )
    }
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

该函数接收多个函数作为参数,然后返回一个函数,该函数又返回一个函数(说真的不喜欢这样的千层饼。。。),而这个函数则返回解散的store和dispatch

在最内层的函数立刻,首先通过createSotre创建了一个store,然后定义了一个奇葩版的dispatch,也就是说在使用中间件里严禁调用dispatch

然后通过map将state和奇葩版的dispatch传入中间件,最后通过compose将其dispatch作为千层饼最内层被中间件一层一层的裹起来,这样日后调用dispatch就必然会调用一层一层的中间件。(dispatch的结果作为参数),最后将这些值作为返回值


最后是我自己写的一个超简易版redux,功能不及正版redux强大,但胜在简单,有兴趣的朋友可以看一下

diaotai/myreduxgithub.com图标

redux的内容在redux文件夹内,clone后npm install最后npm start即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值