之前, 已经写过一篇 redux 源码解读(一) https://github.com/zhanyuzhang/chess-blogs/issues/3 , 主要分析了 redux 的核心思想, 并用 100 多行代码实现一个简单的 redux . 但是, 那个实现还不具备合并 reducer 和添加 middleware 的功能.
今天我们一起来看看合并 reducer (即 combineReducers) 的原理和实现.
在分析原理之前, 先来看看 combineReducers 的用法:
- import { createStore, combineReducers } from 'redux';
- const addScore = (state, action) => {};
- const deleteScore = (state, action) => {};
- const rootReducer = combineReducers({addStore, deleteScore});
- const store = createStore(rootReducer);
从上面的例子可以看出, combineReducers 接收的参数类型是一个原生对象, 其中这个对象的每个键值都是一个 reducer 纯函数. 另外, 因为 combineReducer() 返回的结果可以传递给 createStore 作为参数, 可以推出它返回的结果也是一个 reducer 函数.
了解了 combineReducer 用法之后 , 那开始一步一步的用代码来实现其功能吧.
首先, 需要先声明 combineReducers 的参数, 然后判断传进来的参数是不是原生对象类型 ( plain object ), 如果不是, 则抛出异常, 如果是, 则需要获取该对象的所有属性(key) 并存放到变量 reducerKeys 里面, 然后对这些 key 进行遍历, 过滤掉那些不是函数的值, 并将结果放到 finalReducerKeys 里面. 代码如下:
- export default function combineReducers(reducers) {
- // 判断参数 reducers 是否为对象
- if(Object.prototype.toString.call(reducer) !== '[object Object]') {
- throw new Error('combineReducers expected plain object params');
- }
- const reducerKeys = Object.keys(reducers);
- let finalReducerKeys = [];
- // 过滤掉 value 不是 Function 类型的键名, 然后将结果放到 fianlReducerKeys 里面
- reducerKeys.forEach((key, i) => {
- if(typeof reducers[key] === 'function') {
- finalReducerKeys.push(key);
- }
- });
- }
前面已经提到过了 combineReducers 返回的结果是一个纯函数. 那这个返回的函数需要处理些什么逻辑呢? 因为他合并了其他的 reducers, 所以需要遍历这些 reducer 并执行他们. 然后, 并对比一下执行 reducer 之后的数据有没有变化 , 如果有变化则返回新的 state, 否则直接返回之前的 state. 代码如下:
- export default function combineReducers(reducers) {
- // 省略和前面相同的部分
- // 返回一个新的, 经过组合的 reducer 函数
- return function(state = {}, action) {
- let hasChanged = false;
- const nextState = {};
- // 遍历 finalReducerKeys, 并调用对应的 reducer.
- finalReducerKeys.forEach((key, i) => {
- const stateForKey = state[key];
- const nextStateForKey = reducers[key](stateForKey, action);
- nextState[key] = nextStateForKey;
- // 如果前后状态不一样, 则 hasChanged 设为 true
- if(stateForKey !== nextStateForKey) {
- hasChanged = true;
- }
- });
- // 如果有变化, 则返回新的 state, 否则返回旧的
- return hasChanged ? nextState : state;
- }
- }
OK,redux 源码解读(二)就写到这里, 今天周五啦, 祝大家周末愉快哈! 如果对 combineReducer 还有不明白的地方, 欢迎留言讨论哈. 另外, 可能有些地方我分析得不到位的, 建议到我的 github 去下载代码自己再好好研究一下. 重要的事情说三遍: 代码在这里下载 https://github.com/zhanyuzhang/redux-with-combine-reducers ! 代码在这里下载 https://github.com/zhanyuzhang/redux-with-combine-reducers ! 代码在这里下载 https://github.com/zhanyuzhang/redux-with-combine-reducers !
来源: https://www.cnblogs.com/yugege/p/9416059.html