combineReducers的使用
本小节我们将自己实现一个我们程序可以用的combineReducers函数,并带大家看一看Redux是怎么样实现combineReducers函数的。
1、简单combineReducers函数的实现
在写combineReducers之前我们先来了解一下combineReducers是用来干嘛的。
大家知道我们的reducer最终返回的是一个完整的state,combineReducers起的作用就是将每个子reducer拼接起来返回一个完整的state,那么写出一个简单的combineReducers就不难了。
看下面的例子:
function todoApp(state = initState,action){
return {
filter:setFilter(state.filter,action),
todos:todos(state.todos,action)
};
}
2、源码中的combineReducers
想必大家也和我一样想知道源码中的combineReducers又是怎么实现的呢?
原理大家都知道了,就是用来拼接,知道了原理看懂源码也就不难了,下面带大家过一遍下面贴出来的部分源码。
A、首先我们可以看到它用reducerKeys、finalReducers分别记录了键值和子reducer函数
B、返回了一个函数,当然这个函数就是我们的根reducer。下面再看看这个reducer做了什么
C、先通过arguments将state获取,你们可以看到,他也对state做了处理,在这里提醒一下,像我们在源码里看到的一样,大家在写reducer的时候在default一定要返回一个默认的state。
D、再看我们就能看到一个循环,大家都明白,就是用来执行保存在finalReducers中的reducer函数的,用nextState记录获取到state,然后比较获取到的state和是否改变
E、如果改变就返回新的state
希望大家看完之后除了更了解combineReducers之外,还要记住设计reducer的一些原则。
function combineReducers(reducers) {
//获取每个子reducer函数,以及对应的键值
var reducerKeys = Object.keys(reducers);
var finalReducers = {};
for (var i = 0; i < reducerKeys.length; i++) {
var key = reducerKeys[i];
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key];
}
}
var finalReducerKeys = Object.keys(finalReducers);
//......
return function combination() {
var state = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var action = arguments[1];
//......
//执行每个子reducer函数,如果state发生变化,则返回新的state
var hasChanged = false;
var nextState = {};
for (var i = 0; i < finalReducerKeys.length; i++) {
var key = finalReducerKeys[i];
var reducer = finalReducers[key];
var previousStateForKey = state[key];
var nextStateForKey = reducer(previousStateForKey, action);
//......
nextState[key] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
return hasChanged ? nextState : state;
};
}
3、使用combineReducers
当然我们也可以自行实现不同功能的combineReducers,也可以直接明确的写一个根reducer,但是在此我们使用redux提供的combineReducers。
var todoApp = combineReducers({
filter:setFilter,
todos:todos
});