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

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


VB比较两个Excel表格的内容 VB实现Excel按列或行排序 VB删除EXCEL表格指定行 用vb.net写的验证码识别代码 VB删除EXCEL表格指定列 Oracle数据库Windows 2003环境自动备份批处理 VB通过ADODB连接EXCEL表格文件读取数据 使用VBScript卸载软件 Discuz X2用户注册过程SQL Android手机参数表 用jQuery改变图片(image src) 用std::atomic實現簡單的讀寫鎖 ChinaPay网上支付网关.NET开发 VOB生成IFO文件用nero刻录DVD详解 15款开源Android游戏引擎(安卓免费游戏引擎) 将MVC ASPX转换到Razor视图 Word设置目录简明教程 asp.net mvc页面javascript代码中如何使用razor Discuz X论坛数据表结构:用户数据表pre_common_member boost在windows平台下自带超强 IOCP 的ASIO Boost下载和编译安装简明指引 Windows和Linux环境中Boost下载安装编译配置使用指南 Android开发技巧:Android常用类库说明 Android开发技巧:Android 文件系统 Android开发技巧:Android应用程序架构 ASP.NET MVC Razor 输出没有编码的HTML字符串 ASP.NET MVC 3 Razor 在head里包含js文件 JQuery mobile介绍 JQuery Mobile 页面结构 什么是云计算的通俗理解 什么是Hadoop以及与云计算的关系 vc的远程调试 请教一个局域网视音频合成传输的问题!!! 用SQL如何更新数据表的图片? 一个30多岁的人,他刚开始学VC,请问他有前途吗? 关于Cookie的问题,不知道在哪里问合适 谁有用ASP做用MSchart控件生成的饼图源程序给我一份,给他30分! 为什么我的显卡驱动程序安装不上???主板是815Ep的! 请教一个局域网视音频合成传输的问题!!! 不好!出现错误!请帮忙! 有谁对java3d熟悉阿,急需探讨 暴笑中国队连环画 谁能帮帮新手啊!!!!! 如何通过一个网卡用adsl将整个局域带上网 程序中的消息对话框怎么不直接蹦出来,而是要按一下Alt才行? 程序中的消息对话框怎么不直接蹦出来,而是要按一下Alt才行? ListBox->Items->Add()的问题! 为什么我们的局域网内客户机不自动得到dns server 和默认网关??? 请推荐几款多系统启动控制软件 问各位高手一个很菜的问题! 数据窗口中的检索数据问题 毕业设计要交了!急啊!请问fastreport预览时,怎么没有“页面设置”菜单?? SetCellTextColor 的问题 ===读取时如何成比例的改变一张图片的尺寸及大小=== 毕业设计要交了!急啊!请问fastreport预览时,怎么没有“页面设置”菜单?? 意大利终于出线了 QuickRep1.PrinterSettings.duplex中duplex(双重,双向)是怎样用? 怎样使FORM上默认的最大,最小按钮变小一点,比如象OICQ的FORM上按钮? 关于servlet的问题 数组使用的问题,两种下标为什么只一种可以? 关于C语言编写数值计算的,事关人命啊~~~~ 关于组件问题? 急!急!急!一个宽带的问题? 做了个网站,希望大家看看!!!www.gz111.net 谁有window blinds的注册码 在DOS下,如何设置成1024 X 768,256色 如何分页显示XML数据岛内容 非常常见的一个问题,现在也没有解决,请高手帮忙。 公司要求学日语,学三个月,没工资,不知道努力学三个月能否达到凑合能用水平 我在昆明的迪信通买了摩托罗拉998++后才发现上当了!! 紧急求救,关于断电 简单:几个子查询合并为一个记录? 请问如何用sql语句查询一段日期之内的数据? 有没有人做过向excel模版导出数据 用户控件之间如何传递参数? help me !!!数据库无法启动!!! java IDE 开发环境有哪些比较小而快? 我的外遇 [zz] 走漏,去内蒙古出差,回头再见兄弟门! 做三维游戏都用什么工具? 各位,等这本书有消息后,我重发贴给你们加分,请问大家关于《Delphi高级开发指南》 春节期间桂林气温、气候怎样?去旅游应如何穿衣? 将大米装满一次性杯,然后压紧插入筷子,提起筷子后观察并分析我知道杯子提起来了,主要求原因,急!! 用夸张手法改写句子 现在去海南三亚旅游.请问当地气温多少?有什么衣服合适? 粽子叶是什么叶 用夸张的手法改写下面的句子1、天气很冷.2、我的风筝飞得很高.3、他内心非常激动.4、阅览室里非常静.把下面的句子改写成排比句 1、天上的云形态各异,什么样子的都有.2、溪水随着山势变 谁知道钢笔水弄身上怎么办啊 电饭煲连接温控器的3跟线怎么接 运用夸张手法改写下列句子1.工人叔叔搞四化干劲很大.2.听说我入了团,妈妈笑了.3.何小强虽然长得瘦小,但精神很好.4.报告结束了,同学们发出很响的掌声.5.会场里很静. 一水柠檬酸一般与什么化工物品混合使用? 用万能表怎样测电饭煲温控器好坏 非洲河流湖泊河流分布特点:注入印度洋()()主要外流河 注入大西洋()()主要内流河()()主要咸水湖()主要淡水湖() 在电渡车间上班,因都是酸类化学水,硫酸,盐酸铬酸等空气又不好身上起包,极痒请问怎样治疗特别感谢你们了 美的电饭煲的温控器电阻多少欧? 美国境内著名的山脉、湖泊、河流有哪些? 化工油里有酸怎么办 电饭煲的磁性温控器什么情况下是好的?又该如何测量? 世界上最长的河流?世界水利资源最丰富的河流?非洲最深的湖泊是什么湖.非洲最大的湖泊是什么湖? 初中三年有关于描写风、霜、雪、雨的诗句! NH4HCO3,NAHCO3,H2CO3哪个CO32~浓度大, 等物质的量浓度的1元 2元酸和弱酸 哪个ph大 描写雪的优美语句,写作文要用!这两天杭州雪特别大,想写一篇描写雪的作文,需要一些好句子. NaHCO3溶液中:c(CO32- )>c(H2CO3)为什么? 为什么深海鱼可以生活在海洋馆里面?深海鱼不是体内压力很大吗?不是捞上岸就死了吗?为什么在海洋馆的池子里能生存呢? 谁有描写雪的诗句? 美的电饭锅加热几分钟就不加热了?温控器我换过 还是一样的 我们平时吃的深海鱼有哪些?请告诉名称 已知在0.1mol/l的nahso3溶液中有关微粒浓度大小的顺序为c(na+)>c(hso3-)>c(so)已知在0.1mol/l的nahso3溶液中有关微粒浓度大小的顺序为c(na+)>c(hso3-)>c(so42-)>c(h2so3).则溶液中c(h+)_____c(oh-).答案是大于.但 市场上为何能看见活的浅水鱼而看不见活着的深海鱼从物理知识回答 食用深海鱼有哪些 有没有描写雪很纯洁,很白 的诗句 最好有作者 谢了 急~~! 带鱼是一种生活在水深60米左右的一种深海鱼,但在市场上你却没有见到活的带鱼,请你说出其中的原因.是物理题有关液体压强的,不是生活类问题!回答请务必书面一点谢谢! 【追加】水的电离和溶液pH值相关计算题某探究小组在某温度下测定溶液的pH值时发现0.01mol/L的NaOH溶液中,由水电离出的c(OH-) = 10-13mol/L(-13在右上角),求该温度下0.1mol/L的NaOH溶液的pH值水电 氧气变液态氧要高压、低温.我知道要低温,可是高压氧气密度不是变大吗 雪真大,把句子写具体. 深海鱼打捞上来能活么 氧气在低温,高压是是否能变成液体或固体 体积相同的铁块和吕块放入水中都沉入水底,他们受到的浮力相同吗?为什么? 深海鱼无法在池塘中生存的原因 浓度都为0.1mol/L的下列各溶液,pH值顺序?浓度都为0.1mol/L的HCL,NAOH,H2SO4,BA(OH)2,NH4CL,CH3COOH,NA2SO4,它们的pH从小到大的顺序是? 一块冰中含有一个小气泡,浮在水面上,当冰熔化之后水面将()A上升B原来的位置C下降D无法确定说明理由 怎样捉到活的深海鱼据说因为压强原因,深海鱼由深海到浅海会死亡.那么假设在海底深处,用一个密闭的箱子将深海鱼与附近的海水完全封闭起来,再取回海面,那么此时深海鱼还可能存活吗?或 鸡舍另三边长35米,鸡舍的面积是多少平方米 包粽子的叶子是什么.为什么要包粽子.粽子是谁发明的. 改写句子,换用夸张的手法表达这酒啊,真香.夸张:春节来临,商场里人真多.夸张; 鱼的氧气需求!家里有个水缸长40宽18高22的水缸 里面养着2个5厘米左右长的金鱼9个小家伙1个清道夫,有个600L/H的过滤器,请问需要开24小时吗?晚上要不要开呢? 我国北方为什么每年春季常受到沙尘暴的侵袭? 请用夸张和比喻的手法扩展下面的句子厨房里飘来的饭菜得香味,( )急,急, 鱼需要氧气吗?把它放进封闭的瓶子了能活吗? 包粽子用的是什么叶子 甘肃民勤春季沙尘暴频发的地理原因 牛奶里有氧气吗?鱼在牛奶里能活吗? 包粽子的叶子是什么叶子?可以重复使用吗?英文翻译说是竹叶或芦苇叶? 电压力锅温控器怎么换?一定要拆下发热盘吗?(美的机械的) 这些鱼能活多久,从氧气方面考虑用的是矿泉水15cm*9cm的缸,水深7cm,3条金鱼 通过燃烧除去密闭容器中的氧气且不产生其他气体,可选用的物质是A红磷,B蜡烛,C木炭,D煤,说理由 电压力锅中间那个温控器是多度电压力锅中间那个温控器是多少度,在锅中央,像电饭锅磁扛那个位置,但它是温控器,看不到字在上面,不清楚,请同行说下,查到了145度,但手头没有,只有165度的,能 求浓度为0.1mol/L的HCOOH溶液的pH值 写一篇关於去沙滩游泳的英语作文(用现在完成时)是现在完成时!100字左右. 美的智能电饭煲的温控器(磁钢)能用电压力锅的那种温控代替吗?如题,里面的热敏电阻,电压力锅是145,电饭煲看不出来i
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘