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

上集回顾

Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用)

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

1. action的结构是如何的?

2. 如何去定义一个reducer?

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

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

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

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

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

上期我们先解决了前三个疑问,这期我们一起来探索后4个问题。

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

首先我们先撸一个createStore架构出来:

通过这段代码我们知道了传参应该是什么样子和返回了什么。从中我发现了一个问题,createStore接受的是三个参数:1、reducer 2、预加载的state 3、redux-thunk之类的增强器。但是我们平时经常会写成如下这个样子:

我们会在第二个参数就传入了增强器,这跟源代码的参数结构不符哎,但是为什么就可以这么用了。接下来我们就看一下,reducer是如何做这个处理的。

当第二个参数preloadedState的类型是Function的时候,并且第三个参数enhancer未定义的时候,此时preloadedState将会被赋值给enhancer,preloadedState会替代enhancer变成undefined的。有了这么一层转换之后,我们就可以大胆地第二个参数传enhancer了。

解决了这个疑问之后,往下就是解释一下他返回的值是什么东西,这些解答我们就放在下面做解释,这里就不做赘述了。不过在接下去之前,我们得搞清楚下面这组变量代表啥意思。

其中变量isDispatching,作为锁来用,我们redux是一个统一管理状态容器,它要保证数据的一致性,所以同一个时间里,只能做一次数据修改,如果两个action同时触发reducer对同一数据的修改,那么将会带来巨大的灾难。所以变量isDispatching就是为了防止这一点而存在的。

5、dispatch拿到action到底干了啥?

函数dispatch在函数体一开始就进行了三次条件判断,分别是以下三个:

1.判断action是否为简单对象

2.判断action.type是否存在

3. 判断当前是否有执行其他的reducer操作

当前三个预置条件判断都成立时,才会执行后续操作,否则抛出异常。在执行reducer的操作的时候用到了try-finally,可能大家平时try-catch用的比较多,这个用到的还是比较少。执行前isDispatching设置为true,阻止后续的action进来触发reducer操作,得到的state值赋值给currentState,完成之后再finally里将isDispatching再改为false,允许后续的action进来触发reducer操作。接着一一通知订阅者做数据更新,不传入任何参数。最后返回当前的action。

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

在注册订阅者之前,做了两个条件判断:

1. 判断监听者是否为函数

2.  是否有reducer正在进行数据修改(保证数据的一致性)

接下来执行了函数ensureCanMutateNextListeners,下面我们看一下ensureCanMutateNextListeners函数的具体实现逻辑:

逻辑很简单,判断nextListeners和currentListeners是否为同一个引用,还记得初始变量定义那以及函数dispatch内部那两处的代码吗?

这两处将nextListeners和currentListeners引用了同一个数组,而ensureCanMutateNextListeners就是用来判断这种情况的,当nextListeners和currentListeners为同一个引用时,则做一层浅拷贝,这里用的就是Array.prototype.slice方法,该方法会返回一个新的数组,这样就可以达到浅拷贝的效果。

函数ensureCanMutateNextListeners作为处理之后,将新的订阅者加入nextListeners中,并且返回取消订阅的函数unsubscribe。函数unsubscribe执行时,也会执行两个条件判断:

1. 是否已经取消订阅(已取消的不必执行)

2. 是否有reducer正在进行数据修改(保证数据的一致性)

通过条件判断之后,将该订阅者从nextListeners中删除。看到这里可能有小伙伴们对currentListeners和nextListeners有这么一个疑问?函数dispatch里面将二者引用同一个数组,为啥这里将二者分别引用两个值相同的数组?直接用currentListeners不可以吗?这里这样做其实也是为了数据的一致性,因为有这么一种的情况存在。当redux在通知所有订阅者的时候,此时又有一个新的订阅者加进来了。如果只用currentListeners的话,当新的订阅者插进来的时候,就会打乱原有的顺序,从而引发一些严重的问题。

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

getState相比较dispatch要简单许多,返回currentState即可,而这个currentState在每次dispatch得时候都会得到响应的更新。同样是为了保证数据的一致性,当在reducer操作的时候,是不可以读取当前的state值的。

看完是不是已满腔热血

充满了斗志?

原文地址:https://www.cnblogs.com/dtstack/p/10399983.html

时间: 2024-08-28 18:09:20

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

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

本萌最近被一则新闻深受鼓舞,西工大硬核“女学神”白雨桐,获6所世界顶级大学博士录取 货真价值的才貌双全,别人家的孩子 高考失利与心仪的专业失之交臂,选择了软件工程这门自己完全不懂的专业.即便全部归零,也要证明自己,连续3年专业综合排名第一,各种获奖经历写满了5页PPT.成功始于不断的努力和拼搏,在学习和实践中不断提升自己. #技本功#愿做你成功路上的基石,赶紧来接收今日份的精神投食~ 一.解读type 执行计划的type表示访问数据类型,有很多种访问类型. 1.system表示这一步只返回一行数

android版知乎日报客户端应用源码

如你所见,这是一个知乎日报客户端,我给它起名为:知乎小报,大家可以下载安装体验一下,见附件.IOS版本源码:http://code.662p.com/view/9004.html因为有大把的时间需要在地铁上度过,而我又喜欢知乎日报中的内容,于是就想自己也开发一个知乎日报的客户端,没有让人皱眉的启动页广告,没有应用推荐,没有后台的消息推送,只提供最初的阅读功能.经过了一段时间的开发,最初的设想已经全部完成: 最新新闻.过往的新闻的展示 下拉刷新数据 新闻正文的展示(WebView的各种使用) 正文

知乎专栏应用客户端源码项目

第三方的app,引用作者的描述:"最近一直在利用空余时间开发一个完整的App,名字就叫"专栏".开发这个App的目的主要是为了练练手,熟悉开发一个完整App的流程.就像造房子,亲手打地基,搬砖头,垒砖头,还自己装修(虽然装修的不好看)" Dependency - 依赖 Java Development Kit (JDK) 7 + com.android.tools.build:gradle:1.0.0 Android SDK Android SDK Build-to

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

swift开发的知乎日报客户端详细源码,里面分UI和网络两个模块. 1.涉及到了大部分的UI控件的使用(甚至包括UIRefreshView,UITableConrol等等)2.Connection完成网络的交互操作3.json格式的数据解析4.sqlite数据库的各种常用操作5.包含swift开发过程中常用的工具类它能帮助开发者快速的进入到swift的开发中,而不需要慢慢的去学习swift的基本语法,能快速的提高swift的运用能力. <ignore_js_op>   <ignore_j

android精选源码,知乎阅读瀑布流loading弹窗扫描二维码简洁的MVP

Android知乎阅读与网易音乐功能源码 Android用瀑布流展示美女图片源码 一个简洁好看的loading弹窗 QRCode 扫描二维码.扫描条形码.相册获取图片后识别.生... 一个Android 轻量级简单易用的Log组件 android猎豹快切App源码 android金融VIP pad版 android智能图片裁剪框架源码 android移动网页浏览器源码 超级清晰易懂简洁的MVP

[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)

原文:[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不殆) [推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) 得到了大家的强力支持与建议,万分感谢.接下来介绍下一篇:oracle pl/sql异常处理部分,还望大家一定

【转】[推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼、百战不殆)

[推荐]ORACLE PL/SQL编程之五: 异常错误处理(知已知彼.百战不殆) 继上三篇:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) 得到了大家的强力支持与建议,万分感谢.接下来介绍下一篇:oracle pl/sql异常处理部分,还望大家一定要支持与推荐呀~! 本篇主要内容如下: 5.1 异常处理概念 5.1.1 预定义的异常

高仿精仿饭否客户端应用源码

今天给大家介绍一款非常不错的饭否客户端应用源码,该应用跟现实中的饭否应用功能差不错,界面也很类似,基本实现了饭否应用的功能,喜欢的朋友可以下载学习看看,希望大家功能喜欢. 应用预览图:<ignore_js_op> <ignore_js_op> <ignore_js_op> FanfouData.cs:下载解析返回的数据,数据格式为xml FanfouStatus.cs:返回"随便看看"数据的模型 FnafouUser.cs:饭否用户的数据模型 WP7

知其然知其所以然--Properties.Settings.Default.Save();

winform提供自带的配置,最近查看了一下,数据到底保存到什么地方去了 主目录在这下面C:\Users\Administrator\AppData\                 使用的是win7的系统 C:\Users\Administrator\AppData\Local\程序的名字\BmpProject.exe_Url_2zmdfmzmrtwjomeciqta4ch2sieyx4id\1.0.0.0\user 最后一个user是一个xml config类型的 文件 <?xml vers