@GaoyuanHfut
2017-02-23T07:46:02.000000Z
字数 6569
阅读 466
基于HTML的前端界面开发正变得越来越复杂,其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上。而来自Facebook的React框架正是完全面向此问题的一个解决方案,按官网描述,其出发点为:用于开发数据不断变化的大型应用程序(Building large applications with data that changes over time)。相比传统型的前端开发,React开辟了一个相当另类的途径,实现了前端界面的高效率高性能开发。
在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因(如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。React为此引入了虚拟DOM(VirtualDOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。
借用Facebook介绍React的视频中聊天应用的例子,当一条新的消息过来时,传统开发的思路如上图,你的开发过程需要知道哪条数据过来了,如何将新的DOM结点添加到当前DOM树上;而基于React的开发思路如下图,你永远只需要关心数据整体,两次数据之间的UI如何变化,则完全交给框架去做。
可以看到,使用React大大降低了逻辑复杂性,意味着开发难度降低,可能产生Bug的机会也更少。至于React如何做到将原来O(n^3)复杂度的Diff算法降低到O(n),大家可以参考这篇文章。
虚拟DOM不仅带来了简单的UI开发逻辑,同时也带来了组件化开发的思想,所谓组件,即封装起来的具有独立功能的UI部件。React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义成组件,然后将小的组件通过组合或者嵌套的方式构成大的组件,最终完成整体UI的构建。例如,Facebook的instagram.com整站都采用了React来开发,整个页面就是一个大的组件,其中包含了嵌套的大量其它组件,大家有兴趣可以看下它背后的代码。
如果说MVC的思想让你做到视图-数据-控制器的分离,那么组件化的思考方式则是带来了UI功能模块之间的分离。我们通过一个典型的Blog评论界面来看MVC和组件化开发思路的区别。
对于MVC开发模式来说,开发者将三者定义成不同的类,实现了表现,数据,控制的分离。开发者更多的是从技术的角度来对UI进行拆分,实现松耦合。
上图右边使我们往常写的代码,对于React而言,则完全是一个新的思路,开发者从功能的角度出发,将UI分成不同的组件,每个组件都独立封装。
在React中,你按照界面模块自然划分的方式来组织和编写你的代码,对于评论界面而言,整个UI是一个通过小组件构成的大组件,每个组件只关心自己部分的逻辑,彼此独立。这样最外层的界面的Render只需要如下代码:
通过这种方式,每个组件的UI和逻辑都定义在组件内部,和外部完全通过API来交互,通过组合的方式来实现复杂的功能。React认为一个组件应该具有如下特征:
可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件;
可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;
可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;
可测试(Testable):因为每个组件都是独立的,那么对于各个组件分别测试显然要比对于整个UI进行测试容易的多。
上面从总体上介绍了React带来的全新的前端开发方法,以及其带来的影响,并没有介绍如何使用。为了让大家对其有一个具体的印象,这里实际来开发一个简单的组件:Tab选择器。网店的产品页面通常需要这样的控件来选择产品属性,例如选择衣服的颜色。这个控件接受一个数据源展示多个Tab供点击,点击后就选中了某个颜色,界面通常如下图所示。
按传统方式,我们可以用如下代码来实现一个jQuery插件:
用React方式,代码如下:
通过比较可以看到,jQuery插件方式,开发者首先需要考虑控件第一次Render出来时的DOM构建;其次,需要知道如何切换UI上的选中状态。
而React的方式,开发者仅仅需要考虑整体界面的DOM构建,不再需要关心局部更新,每次在一个React的Component上调用setState方法,都会触发render来重建整个界面。从开发思想的角度看,你可以认为每次数据的更新都会做整体的完全刷新。逻辑简单而直接。
如果我们再多考虑一步,控件的值不只在初始化和点击时可以设置,而且还可以通过程序动态的去设置。那么对于jQuery的方案而言,我们需要额外的方法和入口去做对应的UI更新。而对于React方式,则无需做任何改变,外部只需调用setState方法改变它的状态即可。这就是简化UI逻辑带来的好处。

做一个比喻
想想现代物流系统的发展的不同阶段,我们寄一件东西的过程,
没有物流系统时:
打包准备好要送出去的东西;
- 出门到距离家最近的物流公司,填写物品,收件人等基本信息;
- 物流公司替你送物品到你的朋友处,自己可以回家做别的事情了;
- 多了一个中介,要付一定的运送成本,但是东西可以送到远在几千公里之外的其它人了,用一点点钱节约了自己宝贵的时间,完成了以前我们不可能做的事情;
没有物流系统时对应的就是没有使用状态管理的的前端阶段,做一件事情很直接,如果只是送快递给一个特别近的人,那当然是非常方便。就算你要从北京送一个东西到上海,在这个阶段你也可以实现,但是需要付出的代价就太大了。
而出现了各大物流公司对应的就是使用React等框架的阶段,学习React需要付出成本,如果你只需要做简单的事情(比如说你想把东西送给你的邻居),那使用此类框架其实显得特别累赘,把简单的事情复杂化了,但是如果你想做复杂一点的事情(同时寄礼物给三个不同城市的人),那么选择快递公司是不会错的。
那么React和Redux的关系又该如何理解呢?
我觉得我们可以把React比如为一家自建快递系统的公司(京东?),在一定范围内,它的快递系统已经足够好了(部分一二线城市一天内直达),但是要管理这个日益复杂的快递系统,需要公司付出巨大的成本。
Redux可以看做业内最好的第三方快递系统(顺丰?),使用它比较贵(学习成本稍微有点高),但是他到达全国主要城市都会特别快,如果你是一个电商老板,采用这个第三方物流系统之后,你只需要关注于自己的货物,几乎不用再去关心物流怎么办了。
不同于顺丰每一次寄货都要那么高的价格,redux是一个学习一次,就可以免费寄货的优秀第三方快递系统,那我们当然要解散自己的物流公司来采用这个第三方的选择的。不过话说回来,学习是需要有成本的,所以是直接使用React还是学习Redux再使用,这是你一个你需要依据你自己项目的实际情况作出选择的事情。
不过这个例子可能并不足够合适,Redux做的不仅仅是管理原来React里state里面的状态。Redux其实可以接管我们的app里所有的数据。接下来我们具体看看Redux究竟做了什么。
Redux可以做什么??(相对应得vue.js有vuex)
常常听到一种说法,“Redux是一个非常好的状态管理器”,那究竟什么是状态呢。
重新理解前端中的状态
想想我们平时看的网页,app,或者任何其它和我们有交互的东西,我们感觉到交互的发生是因为界面依据我们的行为作出了反馈,界面所有的改变,其实都可以看作是状态的改变,或者说界面会改变是因为我们的某个行为(事件)(click,drag,move...)触发了某个函数,函数造成了状态的改变,进而改变了界面。
如此看来,无论是显示隐藏这种可见的状态,还是从服务器获取更多的数据,这些都可以看做是状态,而这些状态就是我们的Redux要管理的。
换一句比较专业一点的说法吧,状态包括
API State;(数据)
UI State;(UI的表现形式)
为了更好的展示Redux的好,我们回顾一下前端的状态管理史(称为史其实并不合适,以下三种模式现在都有大量人在使用)。
以前
近代
React内部管理状态时期

如上所述,React是一个全新思路的前端UI框架,它完全接管了UI开发中最为复杂的局部更新部分,擅长在在复杂场景下保证高性能;同时,它引入了基于组件的开发思想,从另一个角度来重新审视UI的构成。通过这种方法,不仅能够提高开发效率,而且可以让代码更容易理解,维护和测试。Facebook以这样一种方式将沉淀多年的前端开发经验和技术的积累完全开源出来,值得所有前端开发者去借鉴和学习。并且React在发布一年的时间里就获得了极大的关注,Github上拥有超过1万的Star,相信其对前端开发的方向,甚至Web Component的标准,都将产生一定的影响。
React 官方
- 官网地址:http://facebook.github.io/react/
- Github地址:https://github.com/facebook/react
学习React之前,我们先了解一下它的设计思想,它与如今其他热门的前端框架有什么不同?它能为我们的开发解决哪些痛点?
可以结合一些简单demo去看文章,例如你在看阮一峰的React 入门实例教程时,可结合他写的入门demo,或官方给的demo。当然你也要边学习边自己去写一些简单demo,去改改别人写的一些React 项目。一定要多动手。
一定要边看边写,不要囫囵吞枣的看一遍就好了。
了解React开发流程,作者的编码思路,写作规范。
开发其实不用详细去全看,在你做项目时,遇到不懂的就去查看一下文档,我认为这样效率更高一点。当然你有时间也可以一步步去阅读。
在学习中我们会遇到 一些问题,可以去社区或一些网站寻找答案,下面推荐一些好的React 社区和学习网站。
React是一款非常优秀的前端框架,你要发挥它完全的性能,你就要结合其他一些技术,例如webpack、redux、react-router等。
入门Webpack,看这篇就够了:写的很不错,逐级深入,适合入门,有点长,耐心看完
介绍一些国内外比较好的 React 开源项目。
国内:
- 阿里的 React 组件库
- Ant Design
- 简易留言板
- react-zhihu
- React的扫雷游戏
- 在线聊天室
- 使用React技术栈开发SPA
- 阔论留言评论
- React版cnode社区
- 适合新手学习的Demo, React + react-router + webpack + babel + Node + express + mongodb
国外:
- Relax
- SoundRedux
- Gatsby
- isomorphic500
- NuclearMail
- Picard
- React Color
- Sentry
- react-hn
- Perseus