Redux 中 combineReducers 和 createStore的实现原理

    最近一直在学习 redux, 感到了深深的难过,都两天了,感觉还是不知道怎么写代码,倒不是不知道是Redux 里面涉及的概念,是不知道什么代码该放在哪里。怎么样组织结构。希望再过两天能更清晰。

    Redux

    下面是中间学习到的 combineReducers 和 createStore 的实现原理,了解这些后,确实帮助了我更好的理解整个流程。


    combineReducers 的实现原理

    在探究 combineReducers 的实现原理之前,先看下 combineReducers 的用法:

    1
    2
    3
    4
    const todoApp = combineReducers({
    visibilityFilter,
    todos
    });

    这里为了逻辑上的分离,我们把 reducers 拆分成了 visibilityFiltertodos, 然后利用了 combineReducers 合成了一个 reducer

    先看下我们的 todos 和 visibilityFilter 是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    //todos
    const todos = (state = [], action) => {
    switch (action.type) {
    case 'ADD_TODO':
    //...
    case 'TOGGLE_TODO':
    //...
    default:
    return state
    }
    }
    //visibilityFilter
    const visibilityFilter = (state = 'SHOW_ALL', action) => {
    switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
    return action.filter
    default:
    return state
    }
    }

    我们的 reducers 也是跟这里的每一个分 reducer 一样,都是函数,都要通过传入 (state, action) 来唯一判断下次的状态。所以我们 combineReducers 的作用就是重新生成一个 可以传入 (state, action) 两个值来判断 next 的 state 的值的函数。

    所以这下我们就可以理解下面的代码,combineReducers 的实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    const combineReducers = ( reducers ) => {
    return ( state = {}, action ) => {
    return Object.keys(reducers).reduce(
    ( nextState, key ) => {
    nextState[key] = reducers[key](
    state[key],
    action
    );
    return nextState;
    },
    {}
    );
    };
    };
    export default combineReducers;

    解释下:首先是返回一个可以传入两个参数的函数。所以我们先 return 一个 function, 然后再通过 reduce 函数,遍历每一个 key 值, 然后为对应的 state 赋值为新的函数。

    当我们形成了新的 reducer 以后, 传入任何 的 action 和 status 就会返回一个明确的 状态树了。可能是下面这个样子的:

    1
    2
    3
    4
    5
    6
    7
    8
    {
    visibilityFilter: 'SHOW_ALL',
    todos: {
    id: 0,
    text: 'Hello world',
    completed: false
    }
    }

    createStore 的实现原理

    同样我们先看下 createStore 的用法:

    1
    2
    3
    //let { subscribe, dispatch, getState } = createStore(reducer);
    import { createStore } from 'redux';
    const store = createStore(reducer)

    createStore 通过传入 我们的 reducer 形成一个全局唯一的 store, 这个形成的 store 是一个对象,它有3个方法,分别是:

    1
    2
    3
    store.dispatch()
    store.subscribe()
    store.getState()

    所以其实我们就是要编辑一个函数,这个函数里面可以有这三个方法暴露给我们使用。 原理如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    const createStore = ( reducer ) => {
    let state;
    let listeners = [];
    const getState = () => state;
    const dispatch = ( action ) => {
    state = reducer(state, action);
    listeners.forEach(listener => listener());
    }
    const subscribe = ( listener ) => {
    listeners.push(listener);
    return ()=>{
    listeners = listeners.filter(l => l !== listener)
    }
    }
    dispatch({});
    return {
    getState,
    dispatch,
    subscribe
    }
    }

    可以看到我们是先实现了这三个方法。下面简单看下怎么用这三个方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const {createStore} = Redux;
    const store = createStore(reducer);
    const render = () => {
    document.body.innerHTML = store.getState();
    }
    store.subscribe(render)
    render();
    document.addEventListener('click', ()=>{
    store.dispatch({type:'INCREMENT'});
    })