Redux源码解读--(2)combineReducers

首先,这里默认读着已经熟练理解Redux的使用了,如果还不是很熟练,请参照Redux,这个是我读过最好的理解Redux的文章。

首先看一下函数的使用方法,要理解最终函数的目的就是把两个Reducer变成一个Reducer导出

function card(state, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
    return {
      name: action.name, // 使用action携带的新name
      picture: state.card.picture  // 不需要修改,使用旧state的值
    }

    default:
    return state  // 没有匹配的action type,返回原来的state
  }
}

function dialog(state, action) {
  switch (action.type) {
    case 'SHOW_DIALOG':
    return {
      status: true
    }

    case 'CLOSE_DIALOG':
    return {
      status: false
    }

    default:
    return state  // 没有匹配的action type,返回原来的state
  }
}

export default combineReducers({
  card,
  dialog
})
combineReducers接受了多个reducer作为参数, 其实参数都是以键值对的形式传入的,只是她们同名了可以简写成这样,如果不想不同名,就要用冒号的形式来写了,比如card:cardReducer,源码中会解释这样写的原因。

export default function combineReducers(reducers) {
  const reducerKeys = Object.keys(reducers)   //遍历传入参数的Key[card,dialog]
  const finalReducers = {}    //最终要得到的结果
  for (let i = 0; i < reducerKeys.length; i++) {
    const 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') {   //reducers[card,dialog],也就是上面自己定义的函数
      finalReducers[key] = reducers[key]    //如果是函数,就放入到返回结果中,key保持不变。这里只是做了过滤
    }
  }
  const finalReducerKeys = Object.keys(finalReducers)   //得到新的key

  let unexpectedKeyCache
  if (process.env.NODE_ENV !== 'production') {
    unexpectedKeyCache = {}
  }

  let shapeAssertionError
  try {
    assertReducerShape(finalReducers)   //判断reducer是否格式正确,该函数作用为当传入的type不存在时,是否会返回默认值。
  } catch (e) {
    shapeAssertionError = e
  }

  return function combination(state = {}, action) {
    if (shapeAssertionError) {
      throw shapeAssertionError   //如果存在不返回默认值的Reducer,抛出异常。
    }

    if (process.env.NODE_ENV !== 'production') {   //发出警告,不影响程序执行
      const warningMessage = getUnexpectedStateShapeWarningMessage(state, finalReducers, action, unexpectedKeyCache)
      if (warningMessage) {
        warning(warningMessage)
      }
    }

    let hasChanged = false   //重点在这下面,是否发生了改变。
    const nextState = {}    //要返回的下一个状态。
    for (let i = 0; i < finalReducerKeys.length; i++) {
      const key = finalReducerKeys[i]
      const reducer = finalReducers[key]   //根据key得到reducer
      const previousStateForKey = state[key]  //这里重点介绍一下,使用该函数要求,每个reducer的key值要和当前操作的state的参数同名,比如我传入card:cardReducer  那么我的state操作的参数就必须是state.card才行,这里印证了答案。
      const nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)  //这里再次验证了是否会返回undefined,即是否有默认值存在,可见框架级别的内容很严谨
      }
      nextState[key] = nextStateForKey   //执行reducer之后的结果
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey  //每次执行之后的结果,再综合上一次得到的结果 hasChanged,得到最终是否state发生了变化
    }
    return hasChanged ? nextState : state  //如果发生了变化就要返回新的state->nextState
  }
}



猜你喜欢

转载自blog.csdn.net/run_youngman/article/details/79086228