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

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


盛大云业务重点转向自服务 转战中小型企业:Prediction API请求一个月内飙升至7亿多次 利用光子 耶鲁大学研究人员让量子计算机离现实更近一步 技术为王的云计算会让IT部门消亡么? 从Discuz到APP:安米移动社区转化工具 覆盖全领域:Google、Facebook、Twitter等大师的最佳推荐 苹果CEO宣布更改保修政策 并向中国用户道歉 拒绝使用现有Web组件的6个愚蠢理由 Github宣布支持SVN方式访问 iPad,正在改变什么? Go Mobile:行业大牛谈行业应用开发 亚马逊Cloud Drive新增文件同步功能 对抗Dropbox 35万奖金发放,BlackBerry 10大赛奖项揭晓 超越Google Apps:排行榜前10的相关云应用 荣耀终将消散 全球第一台千万亿次级超级计算机退役 谷歌已推免费Android和iPhone版Quickoffice,微软你呢? 用于响应式设计的9个CSS技巧 微软Surface Pro正式登陆中国市场 售价6588元起 岳雷:Windows Server 2012虚拟化性能提升巨大 陈健:Windows Server 2012让企业轻松管理IT 智能手机:革命已经波及到阴间 兄贵草泥马:重口味单机移动游戏为什么能火? 最炫HTML5框架Famo.us 将免费面向开发者 MySQL到NoSQL:数据的重思和查询方式的转换 程序员心髓:移动应用API设计10大技巧 Netflix公布个性化和推荐系统架构,3种类型作业通实时 从SendCloud到搜狐云 扎克伯格的败笔?Facebook Home可能无家可归 走进eico design,仰视设计师 乔布斯顾问承认苹果的命名糟透了 罗永浩:一百万年薪!招聘软件研发总监 关于报表打印的问题!火急。。 这个世界上有多少C/C++程序员? 关于ARP广播域的问题????????????????、 请问什么服务器支持global.jsa 安装oracle数据库出错!!!!!!!!!!!! 如何在对话框的OnPaint()函数中得到该对话框的窗口大小? 一个看似简单却很棘手的问题,不得不请教各位。。。 哪里有将rm文件转换成avi或者mpg格式的软件? 关于ARP广播域的问题?????????????? 请问,,怎么设定mshflexgrid的属性,使其各列的宽度与数据源字段的宽度一致 请问这几个对象是否代表同一个对象? 菜鸟问题:如何跟随鼠标拉出一虚线矩形框?回复就有分! 高分寻Authorware v6.0 注册码 在数据窗口中有“部门”和“员工”两个列,分别采用各自的下拉数据窗口显示。如何使得“部门”改变时,“员工”显示与其对应的人员而不是“员工”表中所有人员。 怎样安装UNIX? 灌水加求救…… T-SQL中SELECT句中可不可以有存储过程。。。。。。。。这样为什么不行呢?(100分酬谢) MS SQL SERVER 有谁知道型号为CDU111-NE 的SONY光驱是多少速的吗? 谁对RTTTL格式文件了解,怎么把它转换成可以发送的二进制格式? 关于ORACLE存贮过程的迷惑,请各位大侠解惑! 请问如何向ActiveX控件发送一个自定义数据结构的指针 有没有好一点的ASP上传组件?? asp调用dll失败!!! 为何用了2个以上的单元有调用窗体就出现 access violat at address XXXXX in module的错误 请问有没有一些用来专门用作软件测试的测试软件? EPSONSTYLUS C20SX 型号的打印机支持NT4吗? 请问哪里有linux操作系统的源代码下载?谢谢 哪几种服务器支持global.jsa 关于数据绑定控件的问题。 关于TIFF文件的处理 DLL动态调用的问题,应注意些什么? 有关错误提示问题的文件存放在哪里呀 vf怎样求2个日期类型的差值?象sqlserver的datediff一样。 一个程控交换问题。 请教各位高手,如何在程序中模拟鼠标点击行为,大大加分!!!!!!!!!!!!!!!! 关于一个消息参数的麻烦………………求救高手! 我在微软的网站上下载了一个DCOM的例子,但不能在两台机器上运行? chinajordan(超飞人)请进!!!!!!!!!!!!!!!!!!!! 如果你是sql语句的高手,请看 请问,有谁知道上海华冠电子设备有限公司怎么样的,谢谢! 怎么把一个控件的坐标转换为它的容器坐标!? Canon4650打印测试正常,软件打印预览正常,打出的字横向压缩50%,挤在左边,右为空。 几個很實際也很有用的數据庫問題,請高手指點.(在線等待!) 求教 三千 以及各位Oracle高手。我该做些什么? 救命啊!怎么才能取到她的路径啊??急!!!!!!!!!!! include file为什么不行了 DBGrid的问题... 为什么我执行jsp程序时出现如下错误?[:(!](在下为新手一个) 天哪!csdn的系统到底是怎么了? 请教各位高手,如何在程序中模拟鼠标点击行为,大大加分!!!!!!!!!!!!!! 如何用密度为1.84g/cm3,质量分数为98%的浓硫酸,配制密度为1.14g/cm3、质量分数为20%的稀硫酸400ml I'd like two hamburger for breakfast.句子中有一处错误请找出 They're from Grandpa and Grandma.(对划线部分题问)画Grandpa and Grandma 努力 动词还是名词“努力”是动词还是名词?我需要专业的解释,猜的不要. 为什么do you like hamburger?里的hamburger不加复数而do you like hamburgers for breakfast?要加? 下列溶液中能够用来鉴别BaCl2,NaCl,Na2Co3三种物质的试剂( ),将其滴加到三种试剂中的现象分别是( )( )( ).A.AgNo3溶液 B.稀硫酸 C稀盐酸 D稀硝酸 娱乐是动词还是名词? I want a hamburger for breakfast.(同义句) 一种小瓶装的消毒液净重50克.小明的妈妈买回一些瓜果,现在要将这些瓜果进行消毒(瓜果消毒,消毒液与水的质量比为1:500),取出5克消毒液,需要加水多少克? this that可不可以修饰不可数名词 “交流”是名词和还是动词 怎么回答:What do you like eating for breakfast? this sort of..可以修饰不可数名词吗this kind of 、 this type of 、this sort of 这三个都分别可以修饰不可数名词吗? 现有18.4mol/L的浓硫酸,已知其密度为1.84g/mL,则该浓硫酸溶液中溶质的质量分数为多少? 洗洁精能洗净苹果吗?洗完后苹果上还有农药吗 this/these后面可以接不可数名词吗> 混凝土的天然容重、饱和容重、浮容重、天然内聚力都是多少. 什么叫玉米容重 请问知道岩棉板的长度1000mm宽度630mm厚度50mm容重100KG每立方,怎么算每块的重量?及每吨合多少方?请问知道岩棉板的长度1000mm宽度630mm厚度50mm容重100KG每立方,怎么算每块的重量?及每吨合多少方? i have e bread or hamburger for breakfasti have e______ bread or hamburger for breakfast 初一 玉米容重国家标准是多少?容重与玉米品质的影响如何? 岩棉板 如何计算每立方价钱.如何计算每包价钱.如何计算每平方价钱. I have bread ,mike,sausage and a hamburger anda hamburger _____breakfast 玉米容重和水分 岩棉板的立方怎么计算呢?每吨5000元,厚度5公分,容重40K,有多少立方、每立方又是多少钱,怎么计算呢? I have bread for breakfast. 额,怎么样才能在用水最少的情况下洗干净刚用洗洁精洗过的碗啊盘子之类的 配置1000毫升溶质质量分数为10%的稀硫酸,需要溶质质量分数为98%的浓硫酸多少毫升?同时需要多少克水?具体一点,小弟在此谢过各位大哥大姐们了 I usually have milk and bread for breakfast的答句 A:So have I .B:so do I 洗洁精洗碗几次能洗干净 稀释质量分数为98%(密度1.84g\ml)的浓硫酸配制500g质量分数为20%的稀硫酸,稀释时需要浓硫酸和水的体积各为多少毫升?(水密度1g|\cm*3,结果保留一位小数) Mum shows_____ now to make a hamburger. 要将沾有油的碗洗干净,还有什么方法?(不能用肥皂、洗洁精等)急用! 容重是什么意思?快!快!快! Mum shows ( ) how to make a hamburger. A he B him C his D himself谢谢啦 I often have milk and bread for breakfast.(改为一般疑问句) 从地下挖出来的土体的土容重是什么意思? —Oh.I'm hungry.Mum,can I have the hamburger on the plate?—No.It tastes ( ) .A.terribly B.terrible C.good D.well为什么不是选A 而是选择B 讲知识点 My family often have milk for breakfast 变一般疑问句怎么说?请仔细说明 "broccoli ice cream"是什么意思 .-Oh,I’m hungry.Mum,can I have the hamburger on the plate?-No.It tastes________ A.terribly B.terrible C.good D.well I have eggs and bananas for breakfast.(变一般疑问句) 已知某土土颗粒容重Rs=26.5kn/m3.含水量w=23%,土的容重r=18.47kn/m3,求该土饱和重度及饱和度.设总体积为1,总重量为18.47Kn 这个是已知的土粒重量为:15.02KN 水的重量为:3.45KN 这个土粒重量和水重 hamburger和hamburgers有什么不一样,都分别在什么时候用? He likes milk and eggs for breakfast(改为一般疑问句) 现有一容重为1.2g/cm3的紫色土,起始重量含水量为10%,田间持水量为30%,要使30cm土壤含水量达到田间持水量的80%,需要灌水多少方(方/亩). 小芳的妈妈准备将生吃的瓜果用下面的这瓶消毒液进行消毒,这瓶消毒液需加水多少千克?(消毒液25g)、(说明:1、用法:擦洗浸泡5--6分钟.2、用途:(1)瓜果、餐具类浓度为0.2%(2)衣服及 He has milk for breakfast.改成一般疑问句时为何将has改成have呢,第三人称不是用has的吗?请说明原因. Do they like______?Yes,they do.A.broccoli B.pear C.hamburger D.strawberryDo they like______?Yes,they do.A.broccoli B.pear C.hamburger D.strawberryI like_____but I don't like_______.a.broccoli;tomato b.broccolis;tomato c.broccoli;tomatoes d.broccolis; 如何测定土壤容重掌握土壤容重、比重、孔隙度及三相比的测定与计算方法 现有三瓶失去标签的溶液,分别是H2SO4,NaCl,澄清石灰水,用一种试剂一次鉴别出来,想问一下能加BaCO3吗?参考答案是可溶性的碳酸盐就可以 关于砼容重的问题请解释下容重与平常所说的密度有什么区别.再者例如同为标号C30的两个砼 ,但两者所采用的容重不一样 若一个为2450 另个位2430 请问这两个砼有什么区别?只是质量不同吗,在 土壤容重怎么获取 有一种瓶装消毒液(说明书在下方).小婷妈妈买回2千克瓜果,现需果,取出8克消毒液,需加水有一种瓶装消毒液(说明书在下方).小婷妈妈买回2千克瓜果,现需将这些生吃的瓜果,取出8克消毒 eat的名词是什么,名词是否可数? 土壤容重大小的意义 选出每组单词中不同类的一项.( )1;A;hamburger.B;hand.C;hot dog.( )2;A;duck.B;milk.C;tea.( )3;A;ice-cream.B;French fries.C;pencil-case.( )4;A;juice.B;coffee.C;cat.5;( )A;bread.B;black.C;cake. 砼的容重是多少? 土壤容重大小和土壤深度关系大吗,不同层次土壤容重差别大吗 boiled water boiling water hot water三者区别?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn