夫 子 说

元月二号欠下袋鼠云技术公号一篇关于Redux源码解读的文章,转眼月底,期间常被“债主”上门催债。由于年底项目工期比较紧,于是债务就这样被利滚利。但是好在这段时间有点闲暇,于是赶紧把这篇文章给完成了。据说文章点赞多了可以抵扣利息,小伙们要是觉得我这篇文章还不错的话,记得帮我点赞哦!好让我早日摆脱债务,感激不尽!

好了,回到正题。今天打算和大家讲一讲redux的源码,通过分析源码,我个人觉得受益匪浅,借此通过这篇文章把我的一些心得体会向大家分享一下,另外需要注意一下这次分享的源码用的redux的V4.0.0版本,小伙伴在对照的时候可别搞错咯。接下来老司机可是要发车了,大家抓紧时间上车哦!

在讲源码之前我们首先回顾一下redux是如何使用的,下面我们看一下使用demo:

上面这段代码完整地展示了redux的使用(如果有小伙伴对这段代码不是很理解的话,建议先去学习redux的使用再来看这篇源码,这样更加事半功倍)。通过上段代码,我们拆分几个比较核心的点,我一一列举一下:

1. action的结构是如何的?

2. 如何去定义一个reducer?

3. combineReducers是如何整合多个reducer的?

4. createStore是如何创建一个store?

5.dispatch拿到action到底干了什么?

6. subscribe是如何监听状态发生改变的?

7. getState是如何拿到所有的状态值的?

本期先解决前三个疑问,让我们一起去源码里寻找答案!

1、action的结构是如何的?

首先得解释一下action是干嘛的,它是负责把数据从应用带到store里面,也是store的唯一数据来源,并由以下两个部分组成:

1. type  (操作类型)

2. payload (携带的数据)

为什么得有这两个?其实也很好理解,我们拿银行来类比。某天,你拿着一万块来到银行,走到柜台,人业务员第一件事肯定是问你要办啥业务,存钱?转账?还是还贷?你得把这些告诉业务员,不然业务没法给你办理业务,因此我们action就得有一个type,好让reducer知道你要干啥。当然,你办理存款或者是还款啥的,必不能少的就是毛爷爷了,payload对应的值就好比这些毛爷爷。用一个话来总结action的作用就是:告诉reducer拿着payload去做type这件事。

2、如何去定义一个reducer?

上面讲action的时候,提到了reducer了,这里还是拿我上面的银行做个类比,当我们拿着钱去银行存钱,我们不可能自己去银行把银行保险柜打开,完了把钱放进去,这样是不允许的,我们得需要业务员这个中间人去帮我们做存钱这件事,而业务员所扮演的角色正好就是reducer所要担任的角色。接下来讲一下如何去定义一个reducer,其实reducer的写法并没有绝对的写法,只要符合下面几个条件都能称之为reducer:

1. 必须得是一个函数。

2. 函数接收两个参数。第一个:该reducer所负责的state。第二个:action。

3. 函数体内部可以针对不同的action的type做出响应,这里你可以if-else或者switch-case都是可以的。

4. 函数必须有返回值。当修改state了之后,必须将修改后的state返回。如果遇到未知的type则需要返回一个默认值。

3、combineReducers是如何整合多个reducer的?

我们先看一下combineReducers传入的参数:

combineReducers接受的是一个参数首先得是对象,其次该对象每一个属性对应一个reducer。搞清楚combineReducers的结构之后,我们再看一下combineReducers对其做了哪些处理。

第一步:浅拷贝reducers

这里定义了一个finalReducers和finalReducerKeys,分别用来拷贝reducers和其属性。先用Object.keys方法拿到reducers所有的属性,然后进行for循环,每一项可根据其属性拿到对应的reducer,并浅拷贝到finalReducers中,但是前提条件是每个reducer的类型必须是Function,不然会直接跳过不拷贝。

第二步:检测finalReducers里的每个reducer是否都有默认返回值

assertReducerShape方法主要检测两点:

1. 不能占用redux内部特有的命名空间

2. 如果遇到未知的action的类型,reducer不能返回undefined,得返回默认的值

如果传入type为 @@redux/INIT<随机值> 的action,返回undefined,说明没有对未 知的action的类型做响应,需要加默认值。如果对应type为 @@redux/INIT<随机值> 的action返回不为undefined,但是却对应type为 @@redux/PROBE_UNKNOWN_ACTION_<随机值> 返回为undefined,说明占用了 命名空间。整个逻辑相对简单,好好自己梳理一下。

第三步:返回一个函数,用于代理所有的reducer

先对传入的state用getUnexpectedStateShapeWarningMessage做了一个异常检测,找出state里面没有对应reducer的key,并提示开发者做调整。接着我们跳到getUnexpectedStateShapeWarningMessage里,看其实现。

getUnexpectedStateShapeWarningMessage接收四个参数inputState(state)、reducers(finalReducers)、action(action)、unexpectedKeyCache(unexpectedKeyCache),这里要说一下unexpectedKeyCache是上一次检测inputState得到的其里面没有对应的reducer集合里的异常key的集合。整个逻辑如下:

1. 前置条件判断,保证reducers集合不为{}以及inputState为简单对象

2. 找出inputState里有的key但是 reducers集合里没有key

3. 如果是替换reducer的action,跳过第四步,不打印异常信息

4. 将所有异常的key打印出来

getUnexpectedStateShapeWarningMessage分析完之后,我们接着看后面的代码。

首先定义了一个hasChanged变量用来表示state是否发生变化,遍历reducers集合,将每个reducer对应的原state传入其中,得出其对应的新的state。紧接着后面对新的state做了一层未定义的校验,函数getUndefinedStateErrorMessage的代码如下:

逻辑很简单,仅仅做了一下错误信息的拼接。未定义校验完了之后,会跟原state作对比,得出其是否发生变化。最后发生变化返回nextState,否则返回state。

未完待续

下期预告

《技本功丨知否知否,Redux源码竟如此意味深长(下集)》

THE END

最后,

袋萌萌感谢每一位老铁2018年的陪伴,

生死看淡,不服就干

2019,咱们再战

不断进步

技本功丨知否知否,Redux源码竟如此意味深长(上集)的更多相关文章

  1. 技本功丨知否知否,Redux源码竟如此意味深长(下集)

    上集回顾 Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用) 如果有小伙伴对这段代码不是很理解的话,建议先去学习Redux的使用再来看这篇源码,这样更 ...

  2. 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)

    2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的“圣杯战争“.网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀... 所以,请珍惜以下 ...

  3. 出售Illustrator脚本插件面板(包含面板源码,以及面板上所有的功能源码)

    出售Illustrator脚本插件面板(包含面板源码,以及面板上所有的功能源码) 购买后可提供相应的小修改,以及教你使用往这个多列面里再加上按钮功能! 这套源码可作为工作使用,也可用为新手学习AI脚面 ...

  4. 技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列

    本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取 货真价值的才貌双全,别人家的孩子 高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零, ...

  5. 基于MVVM的知乎日报应用安卓源码

    使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP运行效果: <ignore_js_op> 使用说明: 项目结构 a ...

  6. 第三方知乎专栏应用Android源码

    这是一个国内开发者白瓦力贡献的一个简约的第三方知乎客户端,也许完整度不太高,但感觉还是相当不错的,其实我也是一个知乎迷,尽管平时围观的比较多. 我相信很多搞安卓开发的童鞋也去过知乎解惑吧.引用作者的描 ...

  7. 技本功丨利用 Atomic 构建 React 项目工作流,so easy!

    近日刷微博,#2018年结婚率创新低#荣登热门话题NO.1,沪浙最不积极. 生活压力越大,缺爱的人也越来越多...据本萌的不完全观察,程序猿虽然是压力加成的职业,在袋鼠云还是有不少早早脱了单.至于,脱 ...

  8. 技本功丨用短平快的方式告诉你:Flink-SQL的扩展实现

    2019年1月28日,阿里云宣布开源“计算王牌”实时计算平台Blink回馈给ApacheFlink社区.官方称,计算延迟已经降到毫秒级,也就是你在浏览网页的时候,眨了一下眼睛,淘宝.天猫处理的信息已经 ...

  9. 知乎日报客户端应用ios源码

    swift开发的知乎日报客户端详细源码,里面分UI和网络两个模块. 1.涉及到了大部分的UI控件的使用(甚至包括UIRefreshView,UITableConrol等等)2.Connection完成 ...

随机推荐

  1. IIS中启用CGI来托管PHP和Python网站

    IS中如果要托管PHP和Python的web站点,需要用到CGI来处理HTTP请求,默认情况IIS中是没有CGI模块的,需要在Windows server的服务器管理器(Server Manager) ...

  2. 【Oracle】Oracle安装配置、创建数据库实例及用户和连接

    https://blog.csdn.net/wudiyong22/article/details/78904361 参考资料:https://www.cnblogs.com/hoobey/p/6010 ...

  3. ARC下IBOutlet用weak还是strong

    原文来自这里. 今天用Xcode5的时候,发现默认的IBoutlet的属性设置为weak——因为Xcode5建立的工程都是ARC的了.但是当时还有点不明白,因为项目的原因,一直没有正式使用过ARC.于 ...

  4. hdu_4465_Candy

    LazyChild is a lazy child who likes candy very much. Despite being very young, he has two large cand ...

  5. 【读书笔记 - Effective Java】03. 用私有构造器或者枚举类型强化Singleton属性

    实现Singleton(代表本质上唯一的系统组件)的三种方法: 1. 保持私有构造器,导出公有的静态成员,客户端访问该类的唯一实例. 2. 保持私有构造器,公有的成员是静态工厂方法. 3. 单元素的枚 ...

  6. PHP实现全自动化邮件发送 phpmailer

    PHPmailer           composer地址 function SendMail($msg,$theme,$content) { $mail = new \PHPMailer\PHPM ...

  7. HDU 5212 莫比乌斯反演

    Code Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submis ...

  8. [原创]python写的sniffer

    import socket s=socket.socket(socket.PF_PACKET,socket.SOCK_RAW,8) while 1: data=s.recv(65535) print ...

  9. 【NAS】CIFS用户场景需求分析

    1.everyone用户 1.1: 场景描述:共享目录为rule,所有用户都可以查看,但是不能修改: 解决方法:在smb.conf里配置read only = yes,具体示例如下: [rule] p ...

  10. OpenCV 3.2 FlannBasedMatcher

    #include <iostream> #include <string> #include <boost/timer.hpp> #include "op ...