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

探索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前端大讲堂”。


触摸未来:为什么说AR是未来最重要的人机界面? 科普:谈云计算中间件理念 能准确“猜透”玩家心理,深度学习让游戏更智能 阿里过程改进专家:看板核心在于拉动式管理过程+数据化支持改进 英特尔Edison全面上市,专为小型可穿戴设备设计 APM最佳实践:Web 2.0和AJAX四大优化战略 开放•创新•共赢 2014华为开发者联盟沙龙即将开幕 排名前十的SQL和NoSQL数据库 干货议题,中国互联网安全大会免费门票等你来! 【云先锋】红象云腾:Hadoop将和高铁一样改变我们的生活 IDF 2014上开发者最应关注的三件事之:原生应用兼容性篇 《近匠》WRTnode创始人罗未:OpenWrt,下一个时代的Android AMD爆新一代架构,代号Zen! 【问底】严澜:数据挖掘入门——分词 顺丰集团IT副总裁徐庆强:信息化技术支撑高质量服务 【CTO俱乐部走进雅虎北京全球研发中心】活动图文实录 病毒式传播到商业价值,Docker开创以开发者为主导的商业模式 一周消息树: Windows 9系统截图大量曝光,一起来看看它长什么样! 腾讯李朝晖:不移动非互联,投资关注四大领域 【问底】Yao Yu:谈Twitter的百TB级Redis缓存实践 “OKCoin与你·北京一夜”:共商比特币可持续繁荣之道 苹果再发力:推Apple Pay,或将引发新一轮支付变革 CausalImpact,谷歌开源的R时域因果关系分析工具 腾讯云总裁陈磊:互联网和传统企业互联网化是主线 不得不看,苹果Pay技术大起底! 详解Apple Pay:一大波iOS原生应用正在逼近! 高性能微信公众平台开发 【先锋】事务、高性能,王涛谈打造超越MongoDB的NoSQL 浅谈互联网数据中心海量运营之道 一篇文章读懂开源web引擎Crosswalk Facebook创建新开源组织TODO,Google、Twitter等继续捧场 c++学习中的问题,拿来和大家一起讨论。 求助!要写一个MP3的播放程序~~ Project Settings里面的设置怎么设为默认值,让以后新建的每个工程都适用? 怎样读取数码相机的照片,并将它存入sqlserver数据库中(100分) VB6菜单设计器设计的菜单跟到WINDOWSXP下面,会自动变成XP类型的菜单吗? 请问openpicturedialog的用法? 紧急求教:ScktSrvr(Borland Socket Server)设置问题????????? 关于com与asp的疑惑 怎样读取数码相机的照片,并将它存入sqlserver数据库中 JSP里连接DB2的疑问? 为什么dbgrid的网格颜色属性的更改不是每次都可以。 请教名位大虾!~怎么安装.NET?今天刚买的,却不会装,七张光盘的!~ rose 的问题, SELECT 语句中的WITH TIES作用是什么? 西南交大 农历这么转换成公历?UP有分!急用!问题解决马上给分!不够再加。 关于数组的问题!在线等,谢谢了 不从新发送信息,则无法刷新页面!!! 一个旧声卡怎么才能知道它的型号? 我使出浑身解数,还是装不上sql server2000 ,怎么办? 各位师兄,想问一本书(王国荣的)的书具体内容?! 请问该如何处理?? 请教:关于excel2000链接对象.谢谢() CBC6使用手记--鸡肋 在线等待 如何从一个数据表的某字节中只提出来N个字符!!!!(帮我看一下,谢谢) dbgrid 与 adoquery 的记录如何...? 难道没有人懂水晶报表!??? 季老大帮我搞定!!!!!!!!! 请问该如何处理??在线等 谢谢了!!! 谢谢提供需求分析、概要设计、详细设计、等步骤的样本!!! 用HWiNFO32 V1.22检测机器硬件信息,当检测到“IDE/SCSI Drive(s)”时,硬盘灯常亮并死机,请问是什么原因?是硬件的问题吗? HELP ME AGAIN! 我新买的机器,看看是不是被骗了 谢谢提供需求分析、概要设计、详细设计、等步骤的样本!!! 两个笑话,大家也来帖帖 一个算法,如何快速的从一个大字符串数组里面删除一个小的字符串数组的内容 紧急求救 http://www.driverdevelop.com 好像关了!!! 请问:构件,com,activeX,bean是不是相同的概念?com+和EJB呢? 哪有c++primer第三版? 为何sun one studio在安装模拟器中安装不了6688i 的模拟器?? ComboBox 有问题 我的毕设题目行不行啊? 如何在jsp网页中显示树形目录结构 请问一个计算机本科生出去工作要具备什么条件? 160015.txt怎么取得前面的文件名(160015) 求教高手,java和.net 比,优势在哪里?? 关于wh_callwndproc kook 截获wm-activate 消息 怎样判断两个ACCESS库的表名相同?用代码实现 Our head teacher will be back in a week.对 in a week提问. 硬鳄的天敌是什么 would作为will的过去式为什么用于现在时那?有哪些具体用法.请列举 Have you got used to your school life here英语选择题Have you got used to your school life hereyes but i didn't like ( )when we have to get up early,especialy on cold winter mornings.请问这里为什么不用that ( )( )( )do you have to ask me中文是:你还有别的什么问题要问我吗?括号中可以填What another question吗? 一筐柑橘大约有350个,每次拿3个,每次拿4个,每次拿5个都正拿完,这筐柑橘有几个? 、蝴蝶的幼虫危害农作物,所以蝴蝶是害虫,应消灭它.请判断 学校把3立方米的沙子铺在长3m,宽2m的沙坑里,可以铺多厚?我脑子短路了 一筐柑桔大约有350个,每次拿3个 每次拿4个 每次拿5个都正好拿完 这框柑桔有几个?PS:关于最大公因数和最小公倍数的 go bike riding能不能用在How do you get to school的回答一般情况下问How do you get to school?回答是ride a bike.但是go bike riding作为回答可以吗? 什么动物一叫就走? 苹果 梨 橘子各一筐6筐苹果的千克数=5筐梨的千克数 4筐梨的千克数=3筐橘子的千克数 每筐橘子比每筐苹果 30千克,每筐橘子多少千克? His bag is different from her bag.(改为同义句) 参观滨江区低碳科技馆观后感 一筐桔子大约350个,每拿3,4,5次正好拿完桔子有多少 鲨鱼.鲫鱼.带鱼.草鱼.鲸鱼.那个不是一类的 提高孩子阅读能力探讨之二:如何教孩子做阅读题 世界上走得最慢的是什么动物? His bag is different from others'others'对吗 怎样教孩子阅读理解? 世界上什么动物走的最慢? 鲨鱼,鲤鱼,草鱼,鲸鱼,带鱼,哪一种不属于同类. 为什么说O型血惹蚊子呢? 动物为什么走得慢 "黄鱼 带鱼 鲨鱼" 分一类 "鲢鱼 鲫鱼 草鱼"分一类,为什么 为什么O型血容易惹蚊子 isher lifestyle the same as yours or[ what are the [ 带鱼 草鱼 鲸鱼 鲤鱼 黄花鱼(哪一种不是同一类的?) O型血最惹蚊子喜欢吗? is his lifestyle the same as yours or __________?what My ___to this problem is quite different from his. 急!英语帝进 谢谢A. manner B.Approach c.behavior d.means 最传绣色桃花里指的是什么生肖 烯烃氧化产物到底是什么啊 鲤鱼 草鱼 带鱼 鳗鱼 鲸鱼哪个鱼不是同一类的 为什么防害虫用黄色门帘? 甲乙两个仓库,存货重量相等,从甲仓运走800吨,从乙仓运走500吨,甲仓是乙仓的四分之三,甲乙两仓原有货物多少吨? 仿照示例,根据语境,以草为联想点,在下列文段的横线处各写一个带有哲理意味的句子.字数句式不限示例:"独木不成林,根草不成春'':心心相连,手手相牵才是一道最美丽的风景.1.野火烧不尽,春 黄曲条跳甲是一种什么样的害虫,应该怎样防治 世界上什么动物走的最慢 利用生物的代谢产物进行防治是否属于生物防治 Mary usually has cakes for breakfast at (7 o'clock) .(对括号部分提问) 什么是世界上走的最慢的动物 ------_____will he come back?------In a week.A.------_____will he come back?------In a week.A.How soonB.How often C.How long D.When He usually has breakfast at home为什么用breatfastHe usually has breakfast at home为什么用breatfast 前面不用 a an the 来形容 单烯烃和二烯烃有什么区别 单词拼写.You should get your p____right.You'd better listen to the tapes every day.快.五分钟.有分、、谢谢 1 my lifestyle is different front yours.(改为同义句) My lifestyle _____ _____ _____ _____ yours.2 尽量别吃垃圾食物Try _____ _____ _____ junk food.3 你通常几点放学回家?What time du you usually _____ _____ _____? would rather 啥词性? rather than 呢?I would rather do ………………但是可以I rather than do ………………吗? 橘子每千克1.6元,3.1千克橘子多少元?(估算) 6个同样大的橙子和3个同样大的梨共重1350克一个橙子的质量相当于1个梨的1/3,1个梨重多少克1个橙子住多少克? would rather…than…结构中than是什么词性, 用13.2元买了3千克橘子,用1元钱可以买多少千克橘子? 鳄鱼究竟有没有天敌?自然界是有规律地,从来都有一条食物链.讲究一物降一物,有谁知道鳄鱼有没有天敌?我看所有的电视好像自然界没有能完全收拾的了它的.哪位仁兄能告诉我?别说是人啊, would rather...than 后跟的词是什么词性?什么形式?prefer to后跟的词是什么词性?什么形式? 如何指导孩子做好阅读理解题 水里面有哪些是天敌?鄂鱼有天敌吗? 苹果 梨 橘子各一筐6筐苹果的千克数=5筐梨的千克数 4筐梨的千克数=3筐橘子的千克数 每筐橘子比每筐苹果 多苹果 梨 橘子各一筐6筐苹果的千克数=5筐梨的千克数 4筐梨的千克数=3筐橘子的千 一段长24米的篱笆可以为在一个长8米,宽4米的长方形菜地周围,如果用它围成一个正方形菜地.正方形菜地的面积比长方形菜地的面积多百分之几? 什么动物最会走 ls her lifestyle the same as yours or different?怎么翻译 浙江试发布县级城市空气质量指数 丽水杭州整治两大火车站周边非法黄牛黑车新加坡星展第三季盈利8.62亿新元 日俄防长会谈当天俄军机飞临 日战机紧萨拉热窝两有轨电车相撞 40多人受伤埃及多地爆发大规模反对军方游行【高清环球时报专访中国赴叙利亚参加化学武器会议记录爆奥巴马医改网站开通首天仅6加拿大女子相亲网站“钓男人”吃免费餐梅德韦杰夫谈监听丑闻:美国不能这样厚俄“彼得大帝”号核动力巡洋舰进入地中韩国三四流整形医生赴中国淘金 自称顶近二成美国人称见过鬼 女性比男性更易男子把鸡蛋强塞女子下体后捏碎性侵 辩短短数小时吸金近万 黑采砂船疯狂吞噬双十一:你的订单支付没成功 收到这样平阳孕妇横穿马路被撞倒 村镇干部施救暖湿气流hold住全场 浙江未来一周西湖国际马拉松周日开跑 周边公交线路中国100大最佳市政府出炉 浙江9个近二成美国人称见过鬼 女性比男性更易诗样情怀——这样的礼物太美女子给母亲寄手机 收货时手机变成大米6SensorLabs融资400万美[红豆经典回顾]民国大师们诙谐的风骨高校为新生家长搭夫妻帐篷85%应用存在隐私泄露问题?四成房屋空置或让日本变为无人区世界读书日——重拾阅读,再遇经典【诗词鉴赏】历代帝王诗词精选,你最喜3 x 8 = 23 (火爆了!)贩毒嫌疑人劫持出租车 武警哨兵\"击35条常用文学典故,学会这些没有你读儿童专辑菜谱 轻松让孩子爱上吃饭-南【展览资讯】视觉北京--北京城.家国各种各样的方法自制安全泡泡水懂点风水常识,多点生活经验!希特勒当年是如何对付经济危机的?这几个方法可以帮助宝宝快速入睡,必须专家:国学经典应该成为必修课一个绝佳的免费看剧机会!孩子被欺负了,高手爸妈应该这么办
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘