技本功丨知否知否,Redux源码竟如此意味深长(下集)
上集回顾
Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用)
如果有小伙伴对这段代码不是很理解的话,建议先去学习Redux的使用再来看这篇源码,这样更加事半功倍。通过上段代码,我们拆分几个比较核心的点,我一一列举一下:
- action的结构是如何的?
- 如何去定义一个reducer?
- combineReducers是如何整合多个reducer的?
- createStore是如何创建一个store?
5.dispatch拿到action到底干了什么?
- subscribe是如何监听状态发生改变的?
- 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是否存在
- 判断当前是否有执行其他的reducer操作
当前三个预置条件判断都成立时,才会执行后续操作,否则抛出异常。在执行reducer的操作的时候用到了try-finally,可能大家平时try-catch用的比较多,这个用到的还是比较少。执行前isDispatching设置为true,阻止后续的action进来触发reducer操作,得到的state值赋值给currentState,完成之后再finally里将isDispatching再改为false,允许后续的action进来触发reducer操作。接着一一通知订阅者做数据更新,不传入任何参数。最后返回当前的action。
6、subscribe是如何监听状态发生改变的?
在注册订阅者之前,做了两个条件判断:
- 判断监听者是否为函数
- 是否有reducer正在进行数据修改(保证数据的一致性)
接下来执行了函数ensureCanMutateNextListeners,下面我们看一下ensureCanMutateNextListeners函数的具体实现逻辑:
逻辑很简单,判断nextListeners和currentListeners是否为同一个引用,还记得初始变量定义那以及函数dispatch内部那两处的代码吗?
这两处将nextListeners和currentListeners引用了同一个数组,而ensureCanMutateNextListeners就是用来判断这种情况的,当nextListeners和currentListeners为同一个引用时,则做一层浅拷贝,这里用的就是Array.prototype.slice方法,该方法会返回一个新的数组,这样就可以达到浅拷贝的效果。
函数ensureCanMutateNextListeners作为处理之后,将新的订阅者加入nextListeners中,并且返回取消订阅的函数unsubscribe。函数unsubscribe执行时,也会执行两个条件判断:
- 是否已经取消订阅(已取消的不必执行)
- 是否有reducer正在进行数据修改(保证数据的一致性)
通过条件判断之后,将该订阅者从nextListeners中删除。看到这里可能有小伙伴们对currentListeners和nextListeners有这么一个疑问?函数dispatch里面将二者引用同一个数组,为啥这里将二者分别引用两个值相同的数组?直接用currentListeners不可以吗?这里这样做其实也是为了数据的一致性,因为有这么一种的情况存在。当redux在通知所有订阅者的时候,此时又有一个新的订阅者加进来了。如果只用currentListeners的话,当新的订阅者插进来的时候,就会打乱原有的顺序,从而引发一些严重的问题。
7、getState是如何拿到所有的状态值的?
getState相比较dispatch要简单许多,返回currentState即可,而这个currentState在每次dispatch得时候都会得到响应的更新。同样是为了保证数据的一致性,当在reducer操作的时候,是不可以读取当前的state值的。
看完是不是已满腔热血
充满了斗志?
技本功丨知否知否,Redux源码竟如此意味深长(下集)相关推荐
- 技本功丨知否知否,Redux源码竟如此意味深长(下集) 1
上集回顾 Redux是如何使用的?首先再来回顾一下这个使用demo(谁让这段代码完整地展示了redux的使用) 如果有小伙伴对这段代码不是很理解的话,建议先去学习Redux的使用再来看这篇源码,这样更 ...
- 技本功丨收藏!斜杠青年与你共探微信小程序云开发(下篇)
2019年2月26日,人们为了一个杯子疯了一天. 星巴克猫爪杯,一场已经与猫无关了的"圣杯战争".网上的倒卖价格,已炒至近千元! 求而不得,舍而不能,得而不惜.这是人最大的悲哀.. ...
- 技本功丨请带上纸笔刷着看:解读MySQL执行计划的type列和extra列
本萌最近被一则新闻深受鼓舞,西工大硬核"女学神"白雨桐,获6所世界顶级大学博士录取通知书. 货真价值的才貌双全,别人家的孩子 高考失利与心仪的专业失之交臂,选择了软件工程这门自己完 ...
- 技本功丨收藏!斜杠青年与你共探微信小程序云开发(上篇)
人设千万种,"高危"的大概有两种:好老公/老婆 & 学霸. 猪年第一瓜,演艺事业一帆风顺的翟XX,栽在了学霸的人设上,这件事深刻地教育了我们: 1.学习这件事情来不得一点虚 ...
- 基于MVVM的知乎日报应用安卓源码
使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP 运行效果: <ignore_js_op> 使用说明: 项目结构 ...
- js逆向-知乎最新x-zse-96 逆向源码(2022-09-25更新)
特别声明:知乎x-zse-96逆向分析只是用于研究和学习,请勿他用,否则后果自负 大家好,最近在学习js逆向,自认为学的还可以,于是就找了一个知乎平台练手了,结果不练不知道,越练越费劲呀!那家伙,把我 ...
- android版知乎日报客户端应用源码
如你所见,这是一个知乎日报客户端,我给它起名为:知乎小报,大家可以下载安装体验一下,见附件.IOS版本源码:http://code.662p.com/view/9004.html 因为有大把的时间需要 ...
- 技本功丨呀~我不会写CSS之vertical-align(上集)
某日阅读<CSS世界>,笔者的一段话鞭挞了我的灵魂.原文是这样的-- "说到这里,我就忍不住多说两句.很多其实工作很多年的前端开发人员,也可能不知道vertical-align的 ...
- 技本功丨用短平快的方式告诉你:Flink-SQL的扩展实现
2019年1月28日,阿里云宣布开源"计算王牌"实时计算平台Blink回馈给ApacheFlink社区.官方称,计算延迟已经降到毫秒级,也就是你在浏览网页的时候,眨了一下眼睛,淘宝 ...
最新文章
- 2020-10-26runtime error: member access within null pointer of type ‘struct ListNode‘ (solution.cpp)错
- easy_install与pip 区别
- TCP-IP详解:重传机制
- C++中namespace的理解与实践
- oracle00333,Oracle数据库REDO损坏ora-00333修复手札
- 从0开始详解 Johnson 全源最短路(P5905 【模板】Johnson 全源最短路)
- (23)ISE14.7 PLL输出时钟不能直接输出到普通IO(FPGA不积跬步101)
- java数字类型_Java数据类型
- linux压缩文件命令_Linux基础篇(二)--Linux常用命令
- win11应用商店怎么联网 Windows11应用商店无法联网的解决步骤
- Python基础-类和实例
- CImage 获取图片RGB 、图片高和宽;
- 算法: 最大正方形面积221. Maximal Square
- java构建编译区别_构建与编译(Java)
- 微信小程序搭建tabbar
- 抖音算法推荐机制详解(科普向)
- Java泛型编程思想
- kindle paperwhite2 root 密码修改方法
- linux c open flush,ctrl+c以及写操作失败和flush
- day2(sdasdasdasdasd)
热门文章
- java ehcahce刷新_springboot结合ehcache防止恶意刷新请求的实现
- 关于JavaScript的浅拷贝和深拷贝
- 手把手教你:亲手打造Silverlight的Win8外观(1) 前言
- C语言--关于指针两种初始化赋值操作
- C++ 创建文件夹的四种方式
- 一个简单的内存分配例子
- Android 在布局容器中动态添加控件
- windows内存结构概述
- vba 将html转换excel,利用VBA将不同格式excel模板之间进行数据转换实例
- oracle 在线表分析报告,Oracle Statspack分析报告详解(一)