上一篇有了解到,reducer函数的两个为:当前state和此次dispatch的action。

state的结构是JavaScript对象,每个key都可以代表着不同意义的数据。比如说

  1. {
  2. lists:object,
  3. type:string
  4. }

lists管理列表数据,type管理选中的类型。此时就需要考虑将state分为不同的子树,每次子树数据对应一个reducer子函数,单独管理对应的state。但是createStore(reducer,preloadedState)函数接收的reducer必须为单一个函数。这个时候就需要用到combinReducers函数,它的作用是把多个reducer函数合并成一个最终的reducer函数

combineReducers(reducers)

看一下combineReducers函数实现的核心代码,以下代码删掉了异常提示和处理部分,只保留了关键部分。

  1. export default function combineReducers(reducers) {
  2. //过滤掉参数中,value不是function的
  3. const reducerKeys = Object.keys(reducers)
  4. const finalReducers = {}
  5. for (let i = 0; i < reducerKeys.length; i++) {
  6. const key = reducerKeys[i]
  7. if (typeof reducers[key] === 'function') {
  8. finalReducers[key] = reducers[key]
  9. }
  10. }
  11. // 处理后的reducers对象的所有key值
  12. const finalReducerKeys = Object.keys(finalReducers)
  13. // 返回合并后的reducer函数,她接收的参数和普通的reducer函数一致。
  14. // 这里的state是完整的数据结构,而单一的reducer函数接收的只是它管理的那个子树
  15. return function combination(state = {}, action) {
  16. let hasChanged = false
  17. const nextState = {}
  18. // 有action分派时,对所有的子reducer都触发
  19. // 因为action有type字段,所以还是会触发到对应的之reducer函数
  20. for (let i = 0; i < finalReducerKeys.length; i++) {
  21. const key = finalReducerKeys[i]
  22. const reducer = finalReducers[key]
  23. // 对应的子树数据
  24. const previousStateForKey = state[key]
  25. // 调用对应的reduer函数,返回子树数据的更新结果
  26. const nextStateForKey = reducer(previousStateForKey, action)
  27. // 子树数据同步到state中
  28. nextState[key] = nextStateForKey
  29. // 标记数据是否发生变化,只要有一个子树改变了就算数据已改变
  30. hasChanged = hasChanged || nextStateForKey !== previousStateForKey
  31. }
  32. // 返回state数据
  33. return hasChanged ? nextState : state
  34. }
  35. }

combineReducers接收的reducers是value为子reducer函数的对象。对象的key值可以和函数名一致,也可以不同。返回的state的key值和reducers对象的key值是保持一致的。

所以当createStore(reducer,preloadedState)中的reducer函数是combineReducers合并成的,传入初始状态时,要注意state的keys要和reducers一致

可见combineReducers主要的功能,就是把action传入到所有的子reducer函数遍历一次,同时处理state的切片和合并

当然这里少了很多异常校验部分的代码,有兴趣可以查阅详细源码。

实例

  1. /* reducer */
  2. import {combineReducers} from 'redux';
  3. import testAsync from './testasync';
  4. import todoList from './todolist';
  5. const reducer = combineReducers({
  6. testAsync,
  7. todoList
  8. });
  9. export default reducer;
  10. /* store */
  11. import {createStore} from 'redux';
  12. import reducer from './reducer/index';
  13. let store = createStore(reducer)

{testAsync,todoList}即是reducer函数对象,key和函数名一样。{a:testAsync,b:todoList}写成这样也可以。

state的获取,更新和单一的reducer函数一样,上一篇已做过介绍。

redux源码学习笔记 - combineReducers的更多相关文章

  1. redux源码学习笔记 - createStore

    本篇是学习redux源码的一些记录,学习的redux版本是^4.0.1. 在页面开发时,需要管理很多状态(state),比如服务器响应,缓存数据,UI状态等等···当页面的庞大时,状态就会变的混乱.r ...

  2. Redux源码学习笔记

    https://github.com/reduxjs/redux 版本 4.0.0 先了解一下redux是怎么用的,此处摘抄自阮一峰老师的<Redux 入门教程> // Web 应用是一个 ...

  3. redux源码学习笔记 - applyMiddleware

    在创建store时,createStore(reducer, preloadedState, enhancer),除了reducer函数,初始状态,还可以传入enhancer.这个enhancer在c ...

  4. Redux源码分析之combineReducers

    Redux源码分析之基本概念 Redux源码分析之createStore Redux源码分析之bindActionCreators Redux源码分析之combineReducers Redux源码分 ...

  5. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  6. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

  7. AXI_LITE源码学习笔记

    AXI_LITE源码学习笔记 1. axi_awready信号的产生 准备接收写地址信号 // Implement axi_awready generation // axi_awready is a ...

  8. Hadoop源码学习笔记(6)——从ls命令一路解剖

    Hadoop源码学习笔记(6) ——从ls命令一路解剖 Hadoop几个模块的程序我们大致有了点了解,现在我们得细看一下这个程序是如何处理命令的. 我们就从原头开始,然后一步步追查. 我们先选中ls命 ...

  9. Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构

    Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...

随机推荐

  1. 将字符串向hdfs中写入,出现中文乱码!

    jsonObject.toString():需要处理的json对象转成的字符串 "/testData/ExtractKWByOnce.txt":写入hdfs中的目标路径 try { ...

  2. github node.js

    #安装githubyum install git -y #下载nvmgit clone git://github.com/creationix/nvm.git ~/nvm #设置nvm 自动运行;ec ...

  3. 给pdf添加导航目录

    给pdf添加导航目录 我们下载pdf书籍经常需要以下导航功能,没有导航的pdf根本看不下,接下来会分享我添加导航的方法 首先需要下载工具软件,链接: http://t.cn/Exyss1G 打开软件, ...

  4. Windows上Kafka运行环境安装

    1. 安装JDK 1.1 安装文件:http://www.oracle.com/technetwork/java/javase/downloads/index.html 下载JDK1.2 安装完成后需 ...

  5. HttpHelpers类普通GET和POST方式,带Cookie和带证书验证模式

    HttpHelpers类普通GET和POST方式,带Cookie和带证书验证模式 参考路径:https://www.cnblogs.com/splendidme/archive/2011/09/14/ ...

  6. 团队-爬虫豆瓣top250项目-模块测试过程

    模块测试: 项目托管平台地址:https://github.com/gengwenhao/GetTop250.git 模块测试:"获取250排名的全部电影信息"功能,测试方法:手动 ...

  7. Jmeter+ant集成接口测试报告

    一.jdk1.8下载及环境配置 1.1 下载地址 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-download ...

  8. Django forms表单 select下拉框的传值

    今儿继续做项目,学习了Django的forms生成前端的代码. forms.py class SignupForm(forms.Form): username = forms.CharField(va ...

  9. 组件内守卫beforeRouteEnter和beforeRouteLeave

    beforeRouteEnter用法和其他守卫差不多. 有个注意的地方就是beforeRouteEnter不能用this获取组件内收据. 在next()方法内存入vm这个参数,获取组件内数据. bef ...

  10. 图像之王ImageMagick

    这是我目前能想到的名字.很久前某图像群看到有人推荐过,试了一下确实厉害,支持的格式之多让人叹服. http://www.imagemagick.org/script/formats.php 一般用法 ...