这一小节我们来处理下 reducer 的问题。啥问题?

    我们知道 reducer 是一个计划函数,接收老的 state,按计划返回新的 state。那我们项目中,有大量的 state,每个 state 都需要计划函数,如果全部写在一起会是啥样子呢?

    所有的计划写在一个 reducer 函数里面,会导致 reducer 函数及其庞大复杂。按经验来说,我们肯定会按组件维度来拆分出很多个 reducer 函数,然后通过一个函数来把他们合并起来。

    我们来管理两个 state,一个 counter,一个 info。

    1. let state = {
    2. counter: {
    3. count: 0
    4. },
    5. info: {
    6. name: '前端九部',
    7. description: '我们都是前端爱好者!'
    8. }
    9. }

    他们各自的 reducer

    1. /*counterReducer, 一个子reducer*/
    2. /*注意:counterReducer 接收的 state 是 state.counter*/
    3. function counterReducer(state, action) {
    4. switch (action.type) {
    5. case 'INCREMENT':
    6. return {
    7. count: state.count + 1
    8. }
    9. case 'DECREMENT':
    10. return {
    11. ...state,
    12. count: state.count - 1
    13. }
    14. default:
    15. return state;
    16. }
    17. }
    1. /*InfoReducer,一个子reducer*/
    2. /*注意:InfoReducer 接收的 state 是 state.info*/
    3. function InfoReducer(state, action) {
    4. switch (action.type) {
    5. case 'SET_NAME':
    6. return {
    7. ...state,
    8. name: action.name
    9. }
    10. case 'SET_DESCRIPTION':
    11. return {
    12. ...state,
    13. description: action.description
    14. }
    15. default:
    16. return state;
    17. }
    18. }

    那我们用 combineReducers 函数来把多个 reducer 函数合并成一个 reducer 函数。大概这样用

    1. const reducer = combineReducers({
    2. counter: counterReducer,
    3. info: InfoReducer
    4. });

    我们尝试实现下 combineReducers 函数

    1. function combineReducers(reducers) {
    2. /* reducerKeys = ['counter', 'info']*/
    3. const reducerKeys = Object.keys(reducers)
    4. /*返回合并后的新的reducer函数*/
    5. return function combination(state = {}, action) {
    6. /*生成的新的state*/
    7. const nextState = {}
    8. /*遍历执行所有的reducers,整合成为一个新的state*/
    9. for (let i = 0; i < reducerKeys.length; i++) {
    10. const key = reducerKeys[i]
    11. const reducer = reducers[key]
    12. /*之前的 key 的 state*/
    13. const previousStateForKey = state[key]
    14. /*执行 分 reducer,获得新的state*/
    15. const nextStateForKey = reducer(previousStateForKey, action)
    16. nextState[key] = nextStateForKey
    17. }
    18. return nextState;
    19. }
    20. }

    我们来尝试下 combineReducers 的威力吧

    1. const reducer = combineReducers({
    2. counter: counterReducer,
    3. info: InfoReducer
    4. });
    5. let initState = {
    6. counter: {
    7. count: 0
    8. },
    9. info: {
    10. name: '前端九部',
    11. description: '我们都是前端爱好者!'
    12. }
    13. }
    14. let store = createStore(reducer, initState);
    15. store.subscribe(() => {
    16. let state = store.getState();
    17. console.log(state.counter.count, state.info.name, state.info.description);
    18. });
    19. /*自增*/
    20. store.dispatch({
    21. type: 'INCREMENT'
    22. });
    23. /*修改 name*/
    24. store.dispatch({
    25. type: 'SET_NAME',
    26. name: '前端九部2号'
    27. });

    本小节完整源码见 demo-3