【前端】初识React.js



  • 什么是React?

    很多人可能会对这个问题感到困惑。React 其实不是Augular.js 或者 Backbone.js 那样的MVC 框架。 它只是MVC中的V — 也就是表现层, react 只做一件事,这也是符合UNIX的思路。按官网描述,其出发点为:

    用于开发数据不断变化的大型应用程序(Building large applications with data that changes over time)。

    React最初来自Facebook内部的广告系统项目,项目实施过程中前端开发遇到了巨大挑战,代码变得越来越臃肿且混乱不堪,难以维护。于是痛定思痛,他们决定抛开很多所谓的“最佳实践”,重新思考前端界面的构建方式,于是就有了React。

    React的原理

    在Web开发中,我们常需要将动态数据实时反映到UI上,这就需要产生对DOM的操作。而复杂和频繁的DOM操作会产生性能瓶颈 (DOM对象本身也是一个js对象,所以严格来说,并不是操作这个对象慢,而是说操作了这个对象后,会触发一些浏览器行为,比如布局和绘制,这些会导致整个文档布局的重新计算)。因此,React引入了 Virtual DOM 的机制:

    0_1469732638753_React1.png

    Virtual DOM 是一个模拟 DOM 树的 JavaScript 对象。 React 使用 Virtual DOM 来渲染 UI,当组件状态state 有更改的时候,React 会自动调用组件的 render 方法重新渲染整个组件的 UI。

    那么Virtual DOM为什么能加快网页的渲染呢?

    用React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这种算法可以将复杂度从O(n^3)降低到O(n)。

    在以前的静态网页时代,服务器端所要做的就是根据数据Render出HTML送到浏览器端。如果这时因为用户的一个点击需要改变某个状态文字,那么也是通过刷新整个页面来完成的。服务器端并不需要知道是哪一小段HTML发生了变化,而只需要根据数据刷新整个页面。换句话说,任何UI的变化都是通过整体刷新来完成的。而React将这种开发模式以高性能的方式带到了前端,每做一点界面的更新,你都可以认为刷新了整个页面。至于如何进行局部更新以保证性能,则是React框架要完成的事情。

    这种Render模式也带来开发模式的改变,现在你永远只需要关心数据的整体,而两次数据之间的UI该如何变化,则交给React来做。

    下面用一个例子说明这种变化:

    0_1469734067845_React2.png

    0_1469734101588_React3.png

    React 编程思想

    虚拟DOM不仅带来了简单的UI开发逻辑,同时也带来了组件化开发的思想。所谓组件,即封装起来的具有独立功能的UI部件。React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义成组件,然后将小的组件通过组合或者嵌套的方式构成大的组件,最终完成整体UI的构建。

    如果说MVC的思想让你做到视图-数据-控制器的分离,那么组件化的思考方式则是带来了UI功能模块之间的分离。下面通过一个例子来看下MVC和组件化开发思路的区别。

    对于MVC开发模式来说,开发者将三者定义成不同的类,实现了表现,数据,控制的分离,实现松耦合。

    0_1469734177195_React4.png

    对于React而言,则完全是一个新的思路。功能的角度出发,将UI分成不同的组件,每个组件都独立封装。

    但是你如何知道什么东西应该是独立的组件?只需在你创建一个函数或者对象时,根据是否使用过相同技术来做决定。一种这样的技术是单一功能原则(single responsibility principle),也就是一个组件在理想情况下只做一件事情。如果它最终增长了,它就应该被分解为更小的组件。

    如果你有一个 JSON 的数据模型给用户,你会发现,如果你的模型构建正确,你的 UI就将映射良好。那是因为 UI 和数据模型趋向于相同的信息架构,只需把 UI 拆分成能准确对应数据模型的每块组件。

    这里借用Reac的Document中的一个例子说明这个问题。

    0_1469734216686_React5.png

    在这里你会看到,在我们的简单 APP 里有五个组件。斜体表示每个组件的数据。

    1. FilterableProductTable (橙色): 包含示例的整体
    2. SearchBar (蓝色): 接收所有 用户输入
    3. ProductTable (绿色): 基于 用户输入 显示和过滤 数据集合(data collection)
    4. ProductCategoryRow (蓝绿色): 为每个 分类 显示一个列表头
    5. ProductRow (红色): 为每个 商品 显示一行

    既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中。在模型中,出现在一个组件里面的另一组件 ,应该在层级中表现为一种子级关系:

    • FilterableProductTable
      • SearchBar
      • ProductTable
        • ProductCategoryRow
        • ProductRow

    所以,整个UI是通过一个个小组件组成的大组件,而每个组件只关心自己的逻辑,相互之间是独立的。

    这样最外面的界面只需要render下面的代码:

    1

    ReactDOM.render(
    < FilterableProductTable products={PRODUCTS} />,
    document.getElementById(‘container’)
    );
    // {PRODUCTS} 是数据源*

    通过这种方式,每个组件的UI和逻辑都定义在组件内部,和外部完全通过API来交互,通过组合的方式来实现复杂的功能。React认为一个组件应该具有如下特征:

    (1)可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件;

    (2)可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;

    (3)可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;

    (4)可测试(Testable):因为每个组件都是独立的,那么对于各个组件分别测试显然要比对于整个UI进行测试容易的多。

    小结

    React是一个全新思路的前端UI框架,它接管了UI开发中最为复杂的局部更新部分,在在复杂场景下保证高性能。同时,它又引入了组件式的开发思想,从另一个角度来重新审视UI的构成。通过这种方法,不仅能够提高开发效率,而且可以让代码更容易理解,维护和测试。

    React最近将版本号升级到了从0.14直接跳到了15,移动了其中的小数点,这也说明了React的流行度和Facebook对它的自信。相信React及其组件化的开发思路,将会对前端开发这一社区产生更大的影响。我也非常期待React进一步表现和其生态的健康成熟发展。

    Author: 本文由DMK的Haolin创作

    【DMK小组】DMK寓意为像貂Mink在纽约的冰天雪地中DiaoDeYiBi,勇往前进。DMK由四位小伙伴组织,有着擅长组织爱好数据的rong女侠,干脆直爽技术大拿的靓靓,好学深思勤于实践的阿Ben,勤奋好学积极向上的HaoLin。我们的宣言是“数据是我们的方向,架构是我们的基础”!

    延伸阅读

    深入浅出React(一):React的设计哲学 - 简单之美
    深入浅出React(二):React开发神器Webpack
    深入浅出React(三):理解JSX和组件
    深入浅出React(四):虚拟DOM Diff算法解析
    深入浅出React(五):使用Flux搭建React应用程序架构

    参考文献

    颠覆式前端UI开发框架:React
    Thinking in React



  • Perfect!


登录后回复
 

与 BitTiger Community 的连接断开,我们正在尝试重连,请耐心等待