外村 和仁(株式会社 ピクセルグリッド) 
React.js是什么?

React.js是Facebook开发的框架。

http://facebook.github.io/react/

官网上的描述是「A JavaScript library for building user interfaces」 React.js是用来构造UI的框架。不是一个framework,只是用来构造UI的library,提供MVC中View的机能。

采用了它进行开发的自然有Facebook本身,Instagram、Yahoo、Airbnb等等,是当今备受瞩目的library。

React.js的特征

为了了解React.js的特征,先与其他library或framework相比较。比如像Todo MVC这样对框架进行选型,以发送表单为例子进行实装试验。

jQuery

单纯jQuery的写法:

1
2
3
4
5
6
7
8
9
// 点了Submit之后
$('form').on('submit', functino() {
  // 创建dom元素
  var $li = $('<li>');
  // ...
 
  // 追加到list
  $('ul').append($li);
});

可是,这样被DOM的结构所限制,要追加什么功能都非常麻烦,测试case也不好写。

Backbone.js

Backbone.js可以一定程度上解决类似问题。Backbone.js把管理数据的Model、与管理表现的View分开、然后把View分成各种组件来设计。比如下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
var FormView = Backbone.View.extend({
  onSubmit: function() {
    // 创建data后只要追加到model
    this.collection.add(data)
  }
});
 
var ListView = Backbone.View.extend({
  initialize: function() {
    // model更新后追加到list
    this.collection.on('add', this.render);
  }
});

对FormView或ListView来说、都属于UI的一类功能、同类型的东西都只要调用组件就可以实现。

Backbone.js把数据和组件分开管理以后就更容易管理,但View的更新还需要手动来写仍然非常麻烦,Model与View之间传递事件也变得复杂,代码量扩大的时候就会出现很多问题。(和Backbone.js类似的library比如MarionetteChaplin、本质上问题是一样的)

Angular.js、Vue.js

Angular.js、Vue.js为代表的、所谓MVVM系library的特征是数据一旦发生改变就会自动更新显示。

1
2
3
4
5
6
7
8
9
<form ng-submit="onSubmit()">
  <input type="text" ng-model="text">
</form>
 
<ul>
  <li ng-repeat="item in list">
    {{item.text}}
  </li>
</ul>
1
2
3
4
5
// Controller
$scope.onSubmit = function() {
  // data更新后自动就显示了
  $scope.list.push(newItem);
};

这样记录了HTML中用到的数据、JavaScript就自动把数据更新上去显示了。但是,这种类型的library在规模变大的时候要管理状态是很难的。

React.js

jQuery也好Backbone.js、Angular.js也罢,上面说了都不适应管理大规模的代码。虽然严谨的设计仍然可以成就方便管理的应用。但是,就违背了开发这些框架的本意,代码变得臃肿,设计也不简单。

React.js是规模再大也能提供便利管理的library。相反的,开发高速的小型应用Backbone.js或者Vue.js就更为合适。

React.js的特征是尽量做到组件无状态,便利的对组件进行管理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Form = React.createClass({
  onSubmit: function() {
    // 通知父级数据有更新
  },
  render: function() {
    return <form onSubmit={this.onSubmit}>...</form>;
  }
});
 
var List = React.createClass({
  render: function() {
    // 从父级拿到数据进行更新
    return <ul>{this.props.list.map(...)</ul>;
  }
});

各组件都从父级拿数据然后再去创建View。这一点很重要,组件自身不需要维持状态。通常根据从外部得到的输入进行输出或者测试的情况(大多数情况来自父级组件),管理和复用性都很高。

当然,全部组件都不维持状态的话与静态的HTML并无二致,有一些组件还是需要保持状态的。让尽量少的组件来维持状态,就是设计React.js的初衷。

通常是根节点组件在维持状态,它的子节点组件来传递:

然而,组件的状态一旦改变就会自动刷新树的结构,不需要手动操作,这与Angular.js之类是一样的。

数据一旦改变就自动显示的考虑也相同。

大部分根节点以外的组件都不用保持状态,用户的输入随着用户操作改变的话是需要维持自身的状态。

Virtual DOM

根节点组件保持了状态,它的状态一改变就刷新DOM树的设计非常单纯,一部分的改变导致整个DOM树的刷新影响性能。

这样React.js就引入了Virtual DOM的概念。

Virtual DOM粗略的说,就是构成DOM树的JavaScript对象、计算需要更新数据的对象后再实际更新最少需要更新的DOM元素。

React.js是用React.createClass创建组件,用render方法的返回值得到Virtual DOM。Virtual DOM是React.createElement创建而成的。

1
2
3
4
5
6
7
8
var MyComponent = React.createClass({
  render: function() {
    return React.createElement("div", {className: "foo"},
      React.createElement("div", {className: "bar"},
        "Hello ", this.props.name
      )
    );
});

而且,JSX使用独特的语法,用XML类似的语法来表现Virtual DOM。

1
2
3
4
5
6
7
8
9
10
11
var MyComponent = React.createClass({
  render: function() {
    return (
      <div className="foo">
        <div className="bar">
          Hello {this.props.name}
        </div>
      </div>
    );
  }
});

react-toolsbabel这样的tool可以直接转换成JavaScript。

React.js的性能

有人觉得React.js速度很快,但真的是这样吗?采用了Virtual DOM以后,即便要更新根节点的数据也能最小限度的刷新DOM,确实应该是很快的,比刷新整个DOM树是要快很多。分三种情况进行性能测定:

  1. 用Backbone.js只刷新有变化部分的DOM
  2. 用Backbone.js当部分发生改变却刷新整个DOM树
  3. 用React.js当部分发生改变的时候用Virtual DOM计算好要改动的部分再更新DOM

结果如下图所示:

※ TodoMVC Benchmark

这样的话,React.js、Backbone.js只刷新部分DOM树明显是比刷新整个DOM树要快很多的。

如上所述,只让根节点保持状态是非常简单的设计,在这种简单设计的前提下同样提供比较好的性能,是React.js最大的特点。

Flux

Flux是Facebook非常提倡的一种应用架构设计。经常被拿来和MVC作比较、与MVC不同的是它的数据只有一个流向。

至此为止、作为React.js的设计理念、由根节点保持状态,一旦什么发生改变就刷新那个状态,不管怎样的变更都通知刷新,却不会知道具体是怎样的变更。

例如,DOM树的末端组件检测到用户的操作,需要刷新根节点的状态。这个时候,React.js中这个末端组件是无状态的,必须要立刻通过事件传递通知父级组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var Parent = React.createClass({
  handleChange: function(changedData) {
    // 子元素有什么需要更新的时候
  },
  render: function() {
    // 设定子元素的事件处理函数
    return <Child onChange={this.handleChange}>a</Child>;
  }
});
 
var Child = React.createClass({
  handleSubmit: function() {
    // 父元素接收到事件进行处理
    this.props.onChange(changedData);
  },
  render: function() {
    // 设定表单的事件处理函数
    return <form onSubmit={this.handleSubmit}>...</form>;
  }
});

然而、用这种方法在嵌套较深的情况下更新组件时要传递给用来保持状态的根组件就非常的麻烦。那样,Flux中由View引起的变更进入Action(行为)然后通过Dispatcher(调度)之后Store(存储)后才能完成状态更新。

所谓Store是对数据的管理,相当于MVC模型中的M。View的根节点组件会读取Store中的变化,Store会自动更新数据。

Flux本身的设计理念是如此,实际应用却形形色色。Flux的原始设计是Facebook做的facebook/flux。是最小限度采用Dispacher的例子,其他实例还有如下一些:

总结

上文说明了React.js和Flux的设计思想和特征。React.js适用于有扩展需求的大型项目,却不适合敏捷开发小型应用。那样的需求采用Angular.js或者Vue.js的更多。静态的页面中少许UI单纯用jQuery也很便利。

实际上用过React.js和Flux写过应用就知道,组件要对应状态是一件很麻烦的事。然而,用这些麻烦的代价换来的是具有更强稳定性、更易维护的应用。

如果有这样的需求,还是值得考虑采用React.js的。

当今流行的 React.js 适用于怎样的 Web App?的更多相关文章

  1. 移动web端的react.js组件化方案

     背景: 随着互联网世界的兴起,web前端开发的方式越来越多,出现了很多种场景开发的前端架构体系,也对前端的要求日益增高,早已经不是靠一个JQuery.js来做前端页面的时代了,而今移动端变化最大,近 ...

  2. 当今最流行的Node.js应用开发框架简介

    快速开发而又容易扩展,高性能且鲁棒性强.Node.js的出现让所有网络应用开发者的这些梦想成为现实.但是,有如其他新的开发语言技术一样,从头开始使用Node.js的最基本功能来编写代码构建应用是一个非 ...

  3. 前端迷思与React.js

    前端迷思与React.js 前端技术这几年蓬勃发展, 这是当时某几个项目需要做前端技术选型时, 相关资料整理, 部分评论引用自社区. 开始吧: 目前, Web 开发技术框架选型为两种的占 80% .这 ...

  4. 13个精选的React JS框架

    如果你正在使用 React.js 或 React Native 创建用户界面,可以试一试本文推荐的这些框架. React.js 和 React Native 是流行的用户界面(UI)开发平台,且都是开 ...

  5. Facebook的Web开发三板斧:React.js、Relay和GraphQL

    2015-02-26 孙镜涛  InfoQ Eric Florenzano最近在自己的博客上发表了一篇题为<Facebook教我们如何构建网站>的文章,他认为软件开发有些时候需要比较大的跨 ...

  6. 谈谈 React.js 的核心入门知识

    近来React.js变得越来越流行,本文就来谈一谈React.js的入门实践,通过分析一些常用的概念,以及提供一些入门 的最佳编程编程方式,仅供参考. 首先需要搞懂的是,React并不是一个框架,Re ...

  7. 最流行的Node.js应用开发框架简介

    最流行的Node.js应用开发框架简介 快速开发而又容易扩展,高性能且鲁棒性强.Node.js的出现让所有网络应用开发者的这些梦想成为现实.但是,有如其他新的开发语言技术一样,从头开始使用Node.j ...

  8. Angular、React.js 和Node.js到底选谁?

    为了工作,程序员选择正确的框架和库来构建应用程序是至关重要的,这也就是为什么Angular和React之间有着太多的争议.Node.js的出现,让这场战争变得更加复杂,虽然有选择权通常是一件很棒的事情 ...

  9. React.js 学习笔记

    React.js React.js 是时下最流行的前端 JavaScript 框架之一. 创建工程 # 安装 CLI $ npm install -g create-react-app # 创建新的应 ...

随机推荐

  1. jdk和jre是什么?都有什么用?(转帖)

    jdk和jre是什么?都有什么用?(转帖) 文章分类:Java编程 大家肯定在安装JDK的时候会有选择是否安装单独的jre,一般都会一起安装,我也建议大家这样做.由于这样更能帮助大家弄清楚它们的差别: ...

  2. Makefile详解--隐含规则

    Makefile详解--隐含规则(转) Makefile系列文章,这里有个前辈连续洗了一个系列来介绍,共有26篇博客文章. http://www.cppblog.com/ivenher/archive ...

  3. linux shell pushd popd dirs命令

    1.dirs 1)功能显示当前目录栈中的所有记录(不带参数的dirs命令显示当前目录栈中的记录) 2)语法(1)格式:dirs  [-clpv]  [+n]  [-n](2)选项-c    删除目录栈 ...

  4. oracle设定用户密码使用时间

    强制用户定期更换密码,要怎么设置? 假设密码用10天之后必须修改,宽限期为2天: 把电脑时间往后调十天,然后登录: 系统提示用户密码两天内失效,这时把电脑系统再往后调两天,然后登录: 系统提示密码已经 ...

  5. 用 ISNULL(), NVL(), IFNULL() and COALESCE() 函数替换空值

    在数据库操作中,往往要对一些查询出来的空值进行替换,如函数SUM(),这个函数如果没有值会返回NULL,这是我们不希望看到的, 在MySQL中我们可以这样来写: ) ... 在SQLSERVER中我们 ...

  6. [网络] C# NetHelper网络通信编程类教程与源码下载

    点击下载 NetHelper.zip 主要功能如下所示 检查设置的IP地址是否正确,返回正确的IP地址 检查设置的端口号是否正确,返回正确的端口号 将字符串形式的IP地址转换成IPAddress对象 ...

  7. Android - IOExceptionConnection to xxx refused.

    还是stackoverflow上老外牛,往google上type一下,就找到原因了. 今天在使用Apache提供的HttpClient连接Tomcat服务器,使用log捕获异常的时候,提示说:IOEx ...

  8. A题笔记(2)

    No. 1505 文件读相关 #include <fstream> #include <sstream> <fstream>支持文件的IO <sstream& ...

  9. Hibernate session flush

    最近做项目时,用到了hibernnate,批量删除10000条数据时,删除时前台将id传到后台,用in匹配去删除,页面直接卡死. 解决方法,将传过来的10000条id分批删除,每删除五百条后,调用ge ...

  10. Windows 服务与 Web 服务

    两个完全不同的东西. Windows 服务,伴随着windows的启动而启动,主要处理长时间监听的任务. Web服务,基于Web,部署在服务器上,用于处理客户端的请求.