上一小节,我们把 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 啦!