soulcm / blog

2017开通
6 stars 0 forks source link

redux源码解析(三) #9

Open soulcm opened 7 years ago

soulcm commented 7 years ago

combineReducers

通过前面的学习,我们知道,redux的核心是只有一个store,对于不同业务,不能够拆分store,而是拆分reducer,拆分后的每一块独立负责管理 state 的一部分。

combineReducers 辅助函数的作用是,把一个由多个不同 reducer 函数作为 value 的 object,合并成一个最终的 reducer 函数,然后就可以对这个 reducer 调用 createStore

看它的源码

export default function combineReducers(reducers) {

}

接收的reducers是一个对象,其key为控制state的key的命名,值为各个reducer函数。如调用combineReducers({ counter, todos }),state结果也就为{todos, counter}

刚开始会遍历这个对象,并清理掉值不是function的属性

  var reducerKeys = Object.keys(reducers)
  var finalReducers = {}
  for (var i = 0; i < reducerKeys.length; i++) {
    var key = reducerKeys[i]

    if (process.env.NODE_ENV !== 'production') {
      if (typeof reducers[key] === 'undefined') {
        warning(`No reducer provided for key "${key}"`)
      }
    }

    if (typeof reducers[key] === 'function') {
      finalReducers[key] = reducers[key]
    }
  }
  var finalReducerKeys = Object.keys(finalReducers)

接着进行一系列校验之后,最终返回一个根级的reducer函数,这个函数其实就和自己写子级的reducer函数的结构是一样的。

return function combination(state = {}, action) {
    var hasChanged = false
    var nextState = {}
    for (var i = 0; i < finalReducerKeys.length; i++) {
      var key = finalReducerKeys[i]
      var reducer = finalReducers[key]
      var previousStateForKey = state[key]
      var nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
      var errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    return hasChanged ? nextState : state
}

遍历最终的reducer对象,因为state的结构和reducers对象的结构是一样的,因此可以得到每个state的值var previousStateForKey = state[key] 然后调用它的reducer函数,将会返回一个新的state,本身约定缺省值是返回的初始的state,不能返回undefined。

nextState和previousState比较,判断state是否改变,若改变了,即返回全新的state,没改变就返回老的state。return hasChanged ? nextState : state

这样就通过拆分reducer,将各个业务模块给分离开来,方便管理了。

参考资料

combineReducers 用法

combineReducers 进阶