汪微的博客
zane,做一个有思维的开发者

汪微的博客

redux v3.7.2源码解读与学习之 combineReducers

2017年12月17日45 browse

redux是什么、有什么作用,解决什么问题,如果你还不知道,请先去这里: redux中文文档

下面的文章适合对redux有一定理解和使用经验的人

项目github地址:https://github.com/wangweianger/redux-source-code-learning

如果你觉得对你有帮助的话记得给我一个star 呢


combineReducers是redux的一个核心辅助函数,把多个reducer 合并成一个reducer集合,按key值来区分各个reducer,最终大致数据结构如下:

{
  reducer1: ...
  reducer2: ...
}



最直白的注解,就是干了下面这个事情返回了combination函数。

//有三个函数
let initstate={number:1}
function a(state=initstate,action){
    ...
}
function b(state=initstate,action){
    ...
}
function c(state=initstate,action){
    ...
}

//调用combineReducers方法
const reducers = combineReducers({
    a,
    b,
    c
})

//得到combination这个function  
function combination(state = {}, action){
    const nextState = {
        a:{number:1},
        b:{number:1},
        c:{number:1}
    }

    return nextState
}

//调用的得到 nextState 最终赋值给 createStore方法里面的currentState变量
currentState = combination(currentState,action)



下面让我们来看看源码,我对源码进行了很大的精简,代码如下:

export default function combineReducers(reducers) {
    const finalReducers = reducers
    const finalReducerKeys = Object.keys(finalReducers)

    return function combination(state = {}, action) {
        let hasChanged = false
        const nextState = {}
        for (let i = 0; i < finalReducerKeys.length; i++) {
            const key = finalReducerKeys[i]
            const reducer = finalReducers[key]
            const previousStateForKey = state[key]
            const nextStateForKey = reducer(previousStateForKey, action)
            nextState[key] = nextStateForKey
            hasChanged = hasChanged || nextStateForKey !== previousStateForKey
        }
        return hasChanged ? nextState : state
    }
}


真正的核心代码就这么多,完全可以自己写一个。

给一段测试代码,根据这段代码去理解上面的combineReducers函数

const initialStateHome = {
    home:10,
    cart:20
}

function home (state = initialStateHome, action) {
    switch (action.type) {
    case ADD_SOME_OME:
        return { ...state, home: action.number }  
    default:
        return state
    }
}

function cart (state = initialStateHome, action) {
    switch (action.type) {
    case GET_CART_NUMBER:
        return { ...state, cart: action.number }  
    default:
        return state
    }
}

const reducers = combineReducers({
    home,
    cart,
})



我们根据这个测试案例来分析combineReducers函数:

export default function combineReducers(reducers) {
    /*
    finalReducers的值为
    {
        home:function home(state = initialStateHome, action){...},
        cart:function cart(state = initialStateHome, action){...}
    }
     */
    const finalReducers = reducers
    //finalReducerKeys 的值为: ['home','cart']
    const finalReducerKeys = Object.keys(finalReducers)

    /*
    这里假设调用了  
    store.dispatch({
        type: 'ADD_SOME_OME',
        number: 30
    })
     */
    return function combination(state = {}, action) {
        /*
        此时 action = {type: 'ADD_SOME_OME',number: 30}
            state 的值应该为: {home:10,cart:20}
        */
        let hasChanged = false
        const nextState = {}
        for (let i = 0; i < finalReducerKeys.length; i++) {
            const key = finalReducerKeys[i]
            const reducer = finalReducers[key]
            const previousStateForKey = state[key]
            /*
            这里会匹配到 type: 'ADD_SOME_OME' 也就 home 函数里面的 switch 语句
            匹配之后会得到的值为:nextStateForKey = {home:30}
            而此时的            previousStateForKey = 10
            */
            const nextStateForKey = reducer(previousStateForKey, action)
            //给nextState 赋值  也就是: nextState['home'] = {home:30}
            nextState[key] = nextStateForKey
            //很明显 nextStateForKey !== previousStateForKey 值为 true
            hasChanged = hasChanged || nextStateForKey !== previousStateForKey
        }
        //因此取 nextState 
        return hasChanged ? nextState : state
    }
}



这段代码很好理解,你也可以查看我github源码中 mean-combineReducers.js,和combineReducers.js 有可运行的测试案例,有详细的代码说明。

备注:理解此段代码需要理解透createStore.js, 其中以下代码需要注意到,最终会在这里调用:



接下来我们进入到redux的高阶方法 applyMiddleware

redux v3.7.2源码解读与学习之 applyMiddleware



博主 zane 发表于 2017-12-17 13:19:51,添加在了 redux 标签下

打赏

您的支持将鼓励我继续努力与分享。

扫码打赏,建议金额1-10元

提醒:打赏金额将直接进此方账号,无法退款,请您谨慎操作。

评论

正在加载验证码......

提交