上一小节,我们把 reducer 按组件维度拆分了,通过 combineReducers 合并了起来。但是还有个问题, state 我们还是写在一起的,这样会造成 state 树很庞大,不直观,很难维护。我们需要拆分,一个 state,一个 reducer 写一块。
这一小节比较简单,我就不卖关子了,用法大概是这样(注意注释)
/* counter 自己的 state 和 reducer 写在一起*/let initState = {count: 0}function counterReducer(state, action) {/*注意:如果 state 没有初始值,那就给他初始值!!*/if (!state) {state = initState;}switch (action.type) {case 'INCREMENT':return {count: state.count + 1}default:return state;}}
我们修改下 createStore 函数,增加一行 dispatch({ type: Symbol() })
const createStore = function (reducer, initState) {let state = initState;let listeners = [];function subscribe(listener) {listeners.push(listener);}function dispatch(action) {state = reducer(state, action);for (let i = 0; i < listeners.length; i++) {const listener = listeners[i];listener();}}function getState() {return state;}/* 注意!!!只修改了这里,用一个不匹配任何计划的 type,来获取初始值 */dispatch({ type: Symbol() })return {subscribe,dispatch,getState}}
我们思考下这行可以带来什么效果?
createStore 的时候,用一个不匹配任何 type 的 action,来触发
state = reducer(state, action)因为 action.type 不匹配,每个子 reducer 都会进到 default 项,返回自己初始化的 state,这样就获得了初始化的 state 树了。
你可以试试
/*这里没有传 initState 哦 */const store = createStore(reducer);/*这里看看初始化的 state 是什么*/console.dir(store.getState());
本小节完整源码见 demo-4
到这里为止,我们已经实现了一个七七八八的 redux 啦!
