说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

探索React:组件间通信过程解析

HTML文档下载 WORD文档下载 PDF文档下载
《The React.js Way》系列博文重点分享React所具特性及最佳开发实践。本文为第二篇的译文,重点探讨了React组件间相互通信过程。

近日,RisingStack CTO Péter Márton正在陆续发表《The React.js Way》系列博文,第一篇文章以分享React.js的核心入门知识(中文译文)为主,并讨论了虚拟DOM的概念,以及如何使用组件的思维方式来思考开发的基础上。接下来,需要将它们组合起来运用到实战中去, 第二篇文章则以此为出发点,探讨了React的组件间是如何进行相互通信的。感谢景庄对第二篇文章的翻译,内容如下:

组件即是函数

对于一个独立组件而言,你可以把它看成是一个JavaScript函数。对于函数而言,当你通过传递参数调用函数时,函数会返回给你一个值。 相比之下,对于React组件而言,道理是相似的,你传递属性给组件,而组件则会返回一个被渲染好的DOM。通过传递不同的数据, 相应的你会得到不同的响应。这个过程也就使得React组件能够得到极大的复用,并且你可以很轻松的在应用中重用和组装这些组件。 这种思想实际来源于函数式编程,但其并不在本文的讨论范围中。如果你感兴趣的话,那我强烈建议你阅读Mikael Brevik的 《 Functional UI and Components as Higher Order Functions》, 它可以帮助你更好的理解这个话题。

自上而下渲染

目前为止,我们可以轻松地通过组装组件的方式来构建应用,但此之前,在组件中并没有包括数据。在第一篇文章中,我们讨论过可以在组件层次中的根组件中通过将数据作为参数传递给组件,并且通过层层传递的方式将数据传递给下层组件,也就是说,你在顶层传递数据,它可以一层一层地往下传递, 这个过程,我们称之为自上而下的渲染。


从上层组件往下层组件传递数据其实很简单,但是,如果下层组件发生了某些变化,我们如何通知上层组件呢?例如,用户点击了某个按钮? 我们需要某个东西来存放应用程序的状态数据,能够在状态发生变化的时候去通知所发生的变化。新的状态应该能够被传递给根节点 (最上层节点),然后应该再次发起自上而下的渲染,从而重新生成(渲染)DOM。为了解决这个问题,Facebook提出了Flux架构。

Flux架构

你可能已经听过什么是Flux,也了解它是一种类似于MVC的应用程序设计架构,因此本文不会过多的去探讨什么是Flux,感兴趣的话, 可以阅读《 Flux Inspired libraires with React》这篇文章。

构建用户界面的应用程序架构 —— Facebook Flux

简单总结下:Flux倡导的是单向数据流的原则,在这种架构下,通过Store存放应用程序的状态数据。当应用状态发生变化时,Store可以发出事件,通知应用的组件并进行组件的重新渲染。另外,Dispatcher起到中央hub的作用,它为组件(View)和Store构建起了桥梁。此外,你可以在组件上调用action,它会向Store发起事件。Store正是通过订阅这些事件,并根据事件的触发来改变应用程序的内部状态的。


PureRenderMixin

目前对于我们的应用而言,我们通过一个数据store来存放应用的实际状态。我们可以和这个store进行通信,将数据传递到我们的应用上, 当组件获取新的数据后,进而对视图进行重新渲染。这听起来很赞,但总感觉会经历很多次的渲染,的确是这样的!需要记住的是:组件的层次关系和自然而下的渲染,一切都会根据新的数据来进行响应,做出相应的变化。

在这之前的文章中,我们讨论过虚拟DOM通过一种更为优雅的方式降低了DOM操纵带来的性能损耗,但这并不意味着我们就不需要自己手动进行性能优化了。 对此,基于当前数据和新来的数据之间的差异,我们应该能够告诉组件对于新来的数据是否需要进行视图的重新渲染(如果数据没有发生变化,应该不再重新渲染)。在React的生命周期中,你可以借助shouldComponentUpdate来达成这一目的。

幸运的是,在React中有一种被称为PureRenderMixin的Mixin模式,它可以用来对新的属性和之前的属性进行对比,如果是数据没有发生变化,就不再重新渲染。在内部实现上,它也是基于shouldComponentUpdate 方法的。

这听起来很赞,但遗憾的是,PureRenderMixin并不能很好地进行对象的比较。它只会检查对象引用的相等性(===),也就是说, 对于有相同数据的不同对象而言它会返回false。

boolean shouldComponentUpdate(object nextProps, object nextState)
如果shouldComponentUpdate返回的是false的话,render函数便会跳过,直到状态再次发生改变。(此外,componentWillUpdate和componentDidUpdate也会被跳过)。对于上面所说的问题,我们可以简单的举个例子来说明,有代码如下:

var a = { foo: 'bar' };  var b = { foo: 'bar' };a === b; // false  
可以看到,数据是相同的,但它们隶属于不同对象的引用,因此返回的是false,也因此组件仍然会进行重新渲染,显然这没有达到我们的目的。如果我们想要达成设想的效果(即对于相同数据而言,组件不再重新渲染),我们就需要在原始的对象上进行数据的修改:

var a = { foo: 'bar' };  var b = a;  b.foo = 'baz';  a === b; // true  

虽然实现一个能够进行深度对象比较的mixin来代替引用检查并不困难,但是,考虑到React调用shouldComponentUpdate方法非常频繁,并且对象的深度检查代价较高,所以React选择了这种对象引用比较的方案。

我非常建议你阅读Facebook官方的 有关React应用高级性能的文档。

不变性 Immutability

如果我们的应用状态是一个单一的、大的、嵌套的对象(类似于Flux中的Store),那么上面提到的问题会逐渐升级。

所以当对象的内容没有发生变化时,或者有一个新的对象进来时,我们倾向于保持对象引用的不变。这个工作正是我们需要借助Facebook的Immutable.js来完成的。

不变性意味着数据一旦创建就不能被改变,这使得应用开发更为简单,避免保护性拷贝(defensive copy),并且使得在简单的应用逻辑中实现变化检查机制等。

下面通过一个例子来解释下上面的话。比如,有如下的代码片段:

如上,我们可以使用===来通过引用来比较对象,这意味着我们能够方便快速的进行对象比较,并且它能够和React中的PureRenderMixin 兼容。基于此,我们可以在整个应用构建中使用Immutable.js。也就是说,我们的Flux Store应该是一个具有不变性的对象,并且我们通过 将具有不变性的数据作为属性传递给我们的应用程序。

现在我们回到前面的代码片段来重新想象我们应用程序的组件结构,可以用下面这张图来表示:

如上,我们可以使用===来通过引用来比较对象,这意味着我们能够方便快速的进行对象比较,并且它能够和React中的PureRenderMixin 兼容。基于此,我们可以在整个应用构建中使用Immutable.js。也就是说,我们的Flux Store应该是一个具有不变性的对象,并且我们通过 将具有不变性的数据作为属性传递给我们的应用程序。

现在我们回到前面的代码片段来重新想象我们应用程序的组件结构,可以用下面这张图来表示:

如上,我们可以使用===来通过引用来比较对象,这意味着我们能够方便快速的进行对象比较,并且它能够和React中的PureRenderMixin 兼容。基于此,我们可以在整个应用构建中使用Immutable.js。也就是说,我们的Flux Store应该是一个具有不变性的对象,并且我们通过 将具有不变性的数据作为属性传递给我们的应用程序。

现在我们回到前面的代码片段来重新想象我们应用程序的组件结构,可以用下面这张图来表示:

var stateV1 = Immutable.fromJS({    users: [    { name: 'Foo' },    { name: 'Bar' }  ]});var stateV2 = stateV1.updateIn(['users', 1], function () {    return Immutable.fromJS({    name: 'Barbar'  });});stateV1 === stateV2; // false  stateV1.getIn(['users', 0]) === stateV2.getIn(['users', 0]); // true  stateV1.getIn(['users', 1]) === stateV2.getIn(['users', 1]); // false  

如上,我们可以使用===来通过引用比较对象,这意味着我们能够方便快速地进行对象比较,并且它能够和React中的PureRenderMixin 兼容。基于此,我们可以在整个应用构建中使用Immutable.js。也就是说,我们的Flux Store应该是一个具有不变性的对象,并且我们通过将具有不变性的数据作为属性传递给我们的应用程序。

现在我们回到前面的代码片段来重新想象我们应用程序的组件结构,可以用下面这张图来表示:


从上面的图形中你可以发现,在应用状态发生变化后,只有红色的部分会被重新渲染,因为其他部分的引用数据并没有发生变化。也就是说, 只有根组件和其中一部分的user组件会被重新渲染。

基于这种不变性,能够优化React组件的渲染路径,并通过这种方式来重新思考我们的应用构建和应用性能优化。此外,得益于虚拟DOM, 它能够让React应用比传统应用来得更加高效与快速。(责编:陈秋歌)

译者简介:景庄,前端工程师,关注Node.js、前端工程化。个人博客:http://wwsun.github.com。


欢迎加入CSDN前端交流群2:465281214,进行前端技术交流。  

也可参加CSDN前端大讲堂(微信公开课),享受高含金量在线公开课,与专家讲师在线切磋交流。

如何加入CSDN前端大讲堂?由于该群目前已超过人数限制,所以您首先不得不 扫描下面二维码,加CSDN编辑陈秋歌为好友,然后请她邀请您加入CSDN前端大讲堂微信群。加好友时,请务必注明“申请加入CSDN前端大讲堂”。


怎样建立简单的任务栏应用程序-Delphi资料 增强DelphiTStatusBar控制 制作Delphi的竖排标签 自适应表单的实现-Delphi资料 COM/DCOM的区别与联系-Delphi资料 CoolBar上控件的排列顺序-Delphi资料 Delphi 4 WebBroker Delphi 中自做动态显示的控件 Delphi3的DBGrid中的下拉列表和查找字段编程方法 DELPHI常见问题 Delphi的竖排标签 DELPHI构件制作方法 DELPHI控件Tweblabel的编制 DELPHI中MEMO组件的光标定位 Delphi中RichEdit的奥妙 Delphi中TApplication类 Delphi中日期时间输入的简洁方法 delphi中怎么调用interbase数据库? Memo的Undo功能-Delphi资料 RECT在Delphi中的灵活使用 StringGrid制作只读列-Delphi资料 TADOQuery下主明细表其属性关系如何设置,如何保存主表和明细表?-Delphi资料 TBatchMove用法-Delphi资料 TMemo的真正插入字符-Delphi资料 TREEVIEW的使用-Delphi资料 TreeView在电信综合统计管理系统中的应用-Delphi资料 VB6.0动态加载ActiveX控件漫谈-Delphi资料 捕捉来自 Thread 的异常-Delphi资料 定制Speedbar-Delphi资料 动态产生构件并相应事件-Delphi资料 对Borland可视部件的一处改进-Delphi资料 在DOS下会死机吗? 何为A片?(搞笑 ) vc中执行 select count(*) from table 如何得到返回的数值? 非绑定的,能编辑的网格控件,是什么? SQL 2000 Text数据类型的问题 北京又起沙尘暴了。 我的RED HAT LINUX 的文件系统出了错误,怎样解结?谢谢! 100分请教ActivX控件的注册问题? 如何获得按钮的位置(x y) 请问“GetVolumeInformation( )”函数所获取的“序列号”,在用FORMAT格式化后是否会发生变化? 怎么建立XML树状目录? 救命啊 我也很着急,拜托~~~~~~~~~(关于发布和订阅的简单问题) 在pb中如何自激动窗口,急! 遍了一个简单的servlet,编译时提示:package javax.servlet does not exist! 怎样统计新闻发布系统的新闻点击数 小弟是新手,用GCC编译了一个源文件,生成一个叫a.out的文件,好像是可执行文件,但不知怎样执行,请告知!!! 请问怎样才能用MainFrame类中的函数来控制同一项目中的视(View类)的操作??? 搞个调查:在杭州的程序员年薪有多少K? 请问大虾,Active Dictroy有什么作用,另外到什么地方可以下载? 请问各位仁兄,珠海的2002年程序员考试在哪里报名?谢谢! 如何绕过禁止IP?请指点? 小和尚想开网吧!请问各位高手!网吧应该用什么样的的配置比较好!扩朴方式那总比较好! Question:有没有_获取“视频采集卡”的AV信号 的控件? win98下能安装oracle8i吗? 如何在ASP页面中对XML文档进行询?(问题较多) Insert into TableName values(?,?,?,?,?) 为何写入中文时数据库会是乱码??? 有几个技术问题求助!!!! 有人要去参加Visual studio.net发布会吗 失落中 如何打开被屏蔽的“运行”窗口、注册表编辑器?? 小和尚想开网吧!请问各位高手!网吧应该用什么样的的配置比较好!扩朴方式那总比较好! 哪位能给个简单的dll例子吗?我不知怎样写。 简单问题:谁知道改变屏幕的一块区域的颜色的函数是什末? 有关数字视频监控系统的问题!!! 改错误 打算用PB做个Oracle管理器,请给点意见参考参考 如何在APPLET中读入 HTTP中将其他网页的内容 小女子求教!对您可能非常easy的问题! pb6.5做b/s!求救!送分! 这个问题,我都不好意思问,pb70如何编译成exe文件啊? 集成主板的声、显、网卡的问题。(内详) 怎么连sybase 数据库! 怎样用vb实现ctrl + alt + delete键的功能 求超级兔子魔法设置4.2的注册码,一定高分相送 如何调用数据库中带输入、输出参数的存储过程 ASP页面里用下拉框控制日期显示时,没有31号的月份怎么控制不显示31号呢? 寻EPOC高手。 刚学VC要注意点什么哈 如何将BMP图形转成JPEG后,存入数据呢?请教! 脸红请教! 戊戌变法颁布的法令有和重要历史意义? 静电感应为什么用摩擦后的橡胶棒靠近一个不带电的小球时,小球会一边带正电一边带负电;而当用摩擦后的橡胶棒靠近一个带电的小球时,小球带负电?(说得具体点,通俗易懂一点,因为我才 改革开放的历史起点A.党的十一届三中全会B.党的十二大C.党的十三大 什么叫平行板电容器充电 什么叫做 静电感应?什么叫做 地面静电感应? 在新的历史起点上,我们应如何进一步推进改革开放的历史进程? 两个等量异种点电荷+Q和-Q,相距为r,在它们连线的中点O处放置另一电荷q,则Q所受的电场力的大小是等于谁解释下为什么q受到二个点电荷的库仑力方向相同, 关于静电感应 . 静电感应造成了那些现象? 为了防止静电感应造成危害, 请举例说楚人们的一种做法. 如何理解解放思想,实事求是,与时俱进是邓小平理论和“三个代表”重要思想的精髓? 国体与政体?国体与政体的概念是什么?各个国家的国体和政体是什么?我国的是什么? 机电用英语怎么说 结合实际说明解放思想,实事求是是邓小平理论的精髓一定要结合实际情况, 国体与政体之间的关系 “机电”的英语怎么说? 邓小平理论的精髓是 解放思想 、 实事求是 、 .(填空题) 中国的国体和政体是什么? 一个电子在一匀强电场的某一点受到电场力为3.2×10-12N,则该点的场强大小为 . 如何理解实事求是、解放思想、与时俱进是邓小平理论和三个代表重要思想的精髓 将含一种杂质(其质量小于 0.3g)的丙醛试样 8g,与足量的银氨溶液反应,析出 银 30.6g,则该杂质可能是 A 甲醛 B 乙醛 C 丁醛 D 戊醛如图,还有,我这题是杂质质量小于0.3g,网上都是大于0.3g 我国的国体与政体的关系? 匀强电场的电场力大小是否不变,不是场强不变吗 1787年宪法规定美国的国体是什么A君主立宪制B资产阶级共和制C责任内阁制D联邦制 为什么GB/T18033-2007没有TP2化学成分的要求 匀强电场的场强方向总是和电荷所受电场力方向一致吗?如题. 平行电板电容器充电的时候有电流吗?平行电板之间没有直接相连,空气作为电介质,电板接入电源之前不带电,接入电源之后,负电子移动到一个电板上,正电荷移动到另一个电板上,那么这有没有 相距为r的A、B两点分别带有等量的异种电荷Q和负Q,AB连线中点处的电场强度为?这题我一直不懂,kingtheme~不好意思, 我国宪法的基本原则中华民族优良道德传统的主要内容有哪些 如题.根据我国第一部社会主义宪法规定,我国的国体和政体分别是什么?我国人民代表大会制度和西方的三权分立制度有何本质的区别?三权分立在西方和近代中国是如何付诸实践的? 不锈钢303含镍多少?GB牌号为0Cr18Ni9这个是什么材质呢? 3.合金的晶体结构有哪些类型?性能如何? 平行板电容器在电路中的问题一平行板电容器与阻值为10欧的电阻串连,电源电压为100V,接通开关,电容器是否会有电阻,电路中电流多大,且是否会有电流经过平行板. 不锈钢SUS443对应的国标GB牌号怎么写? 电容器的充电原理是什么? 请问一个电路中的平行板电容器充电过程中,这个电容器的电阻如何变化? 电容器的放电速度于什么有关 说出几种常见合金和组成其合金的金属 为什么说南方周末应该成为北方报业的典范?南方周末做得很好吗?范冰冰跟南方周末有什么关系呢? 参保人姓名英语怎么说阿?谢谢同问~ 电容是通交隔直,为什么在讲原理的时候,即可以充电,也可以放电呢?电容器充电以后,极板上充满了电荷,也就储存了电能,先把开关K投向1的位置,使电容充电,然后拉开开关K向2的位置,我们就会 南方周末好吗? 社保号码用英语怎么说 在改革开放的新的历史起点上,怎样做到事实求是? 南方周末被处罚一共有几次南方周末因报道而遭到官方处罚共有几次,每次都是怎么处理的,这对南方周末的报道思想和报道风格产生过哪些影响请尽快回答~ 详细的加分~ 管理员工社保信息 英语怎么说请帮忙翻译下面的句子,谢谢登记和管理员工的社保和公积金信息. 如何理解只有解放思想才能事实求是,只有事实求是才能解放思想? 关于两个等量异种点电荷在其连线中点的电场强度和电势(规定无穷远处电势为零),下列正确的是(  )关于两个等量异种点电荷在其连线中点的电场强度和电势(规定无穷远处电势为零 电场线方向上的场强大小怎么判断 在改革开放的历史起点上怎样做到事实求是求答案 两个等量的异种点电荷,在其连线中点的电场强度和电势,下列说法正确的是 通过电场线的方向能判断场强大小么?怎么判断? 什么事解放思想和事实求是,其关系是什么? 等量异种电荷,同种电荷连线上中垂线上的特点和电势和电场强度的变化及原因.如为什么等量异种点电荷连线上以中点O场强最小,中垂线上以中点O的场强为最大 等等~ 为什么匀强电场是场强是处处相等,为什么光是判断电场线的稀疏就可确定场强大小呢?请用理论证明一下,不要只描述.匀强电场不是还存在与电荷的距离吗?电场是真实存在的物质,即使匀强 我国宪法的基本原则的基本特征 六方紧密堆积晶胞结构的中心原子在晶胞的体心上吗? H62 铜合金化学成分哪位专家能提供一下H62黄铜的具体化学成分含量.请帮忙列出所有元素的成分含量。 我国宪法的基础原则! 戊戌变法的法令有哪些 这些法令有什么意义 GB/T14976 00Cr17Ni14Mo2的化学成分 我国宪法的基本原则主要是?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘