文章目录
  1. 1. 简介
  2. 2. React 原理
    1. 2.1. 虚拟 DOM
    2. 2.2. 简化的组件模型
    3. 2.3. 例子
  3. 3. 其他概念
  4. 4. 小结
  5. 5. 参考

简介

2013年,facebook 发布了 React。它最初来源于 facebook 内部的广告系统项目,它抛开所谓的“最佳实践”,重新思考前端界面的构建方式,于是就有了 React。

最近发布的这版,与上个版本相比,也有所变化。
1.取消了函数的自动绑定。以前是

1
<button onClick={this.handleSubmit}>Submit</button>

现在是-以 ES6 语法定义

1
<button onClick={this.handleSubmit.bind(this)}>Submit</button>

2.取消了对 mixin 的支持
基于 ES6 的 React 组件,不再能以 mixin 的形式进行代码复用或扩展。因为它增加了代码的不可预测性,无法直观的去理解。可点击查看关于 mixin 的思考
PS:
此处,不在讨论它变化的细节,而是旨在说明一个框架是发展变化的,同时通过改变来窥探下 React。

React 的设计哲学:
以“简单直观”、“符合习惯”的方式去编程,让代码更容易被理解,从而易于维护和不断演化。

React 的最大价值?
1.高性能虚拟 DOM 【★★】
2.声明式的、直观的编程方式(别样的组件化、JSX也不是核心)【★】
3.封装过的事件机制
4.服务器端 Reader(忽略,不是核心,锦上添花)
5.完善的错误提示信息

React 的适用场景:
适用于数据不断变化的大型应用程序,eg.聊天、评论等
会面临问题:如何将服务器端 or 用户输入的数据高效地反应到复杂的用户界面上

React 原理

新的前端 UI 的构建方式:两层编程模型:数据模型、UI界面。数据模型驱动UI界面(从概念角度上看是直观的,而实际开发中困难重重)

React 的初衷之一就是:既然整体刷新一定能解决层叠更新的问题,那我们为什么不索性就每次都这么做呢?让框架自身去解决哪些局部 UI 需要更新的问题-React做到了,实现的途径就是通过虚拟 DOM。

UI界面是一颗 DOM 树。我们再在全局定义一个唯一的数据模型。每次数据模型有任何变化,都将整个数据模型应用到 UI DOM 树上(由 React 来负责更新需要更新的界面部分)。

虚拟 DOM

将变化的数据实时反应到UI上,就要对 DOM 进行操作。复杂和频繁的 DOM 操作,通常是性能瓶颈产生的原因。

虚拟DOM,是在浏览器端用 JS 实现了一套 DOM API。基于 React 的所有 DOM 构造都是通过虚拟 DOM 进行的。每当数据变化时,React 会重 新构建整个 DOM 树,并将当前的树和上一次的 DOM 树进行对比,得到 DOM 结构的区别。然后仅仅将需要变化的部分进行实际的浏览器 DOM 更新。且,React 能够批处理虚拟 DOM 的刷新,在一个事件循环内的两次数据变化会被合并。

虽然,每次都要构造完整的虚拟 DOM 树,但因为它是内存数据,性能极高 【那会消耗多少内存呢?】对实际 DOM 的操作,仅仅是 Diff 部分,故能提高性能。(至于 React 如何做到将原来 O(n^3) 复杂度的 Diff 算法降低到 O(n),感兴趣的你可以再深入学习下)

你永远只需要关心数据整体,两次数据之间的 UI 如何变化,则完全交给框架去做。开发逻辑没那么复杂了,开发难度降低,产生的bug几率也就更少。

简化的组件模型

所谓组件,就是状态机器。对组件的管理 就是对状态的管理。这么,React 很少要暴露组件方法和外部交互,只要设置状态即可,只需要考虑在某个状态下UI是怎样的。

React 将用户界面看做简单的状态机器。当组件处于某个状态时,那就输出这个状态对应的界面,以保证界面的一致性。在 React 中,你只需要简单的更新某个组件的状态即可,然后基于新状态输出整个页面。由 React 负责以最高效的方式去比较两个界面并更新 DOM 树。

组件是 React 中构建用户界面的基本单位。与外界的交互除了 state(状态)之外,还有 props(属性)。事实上,state 更多由组件内部自己维护,props 则由外部初始化该组件时传递进来(一般是组件需要管理的数据)。React 认为,props 应该是只读的(一旦赋值过去就不要变化了)。

虚拟化DOM,不仅简化了UI逻辑,也内含了组件化开发思想。组件,即封装起来的具有独立功能的UI部件。将UI上每一个功能相对独立的模块定义成组件,然后将小的组件通过组合 or 嵌套构成大的组件,最终完成整体UI的构建。

MVC:开发者将三者定义成不同的类,实现了表现、数据、控制的分离(从技术角度拆分UI实现松耦合)
React:新的思路,开发者从功能的角度出发,将UI拆成不同的组件。每个组件都独立封装。即按照界面模块自然划分的方式来组织和编写你的代码。eg.典型的评论界面

对于评论界面而言,拆分UI,每个小组件只关心自己的逻辑,彼此独立。这样最外层的界面 Render 可以这么写:

1
2
3
4
5
6
7
8
9
10
11
var CommentBox = React.createClass({
render: function(){
return (
<div className="commentBox">
<h1>Comments</h1>
<CommentList />
<CommentForm />
</div>
);
}
});

如此,每个组件的UI和逻辑都定义在它们内部,高度自治。和外部完全通过API来交互,通过组合来实现复杂功能。

React 认为,一个组件应该具备以下特征:
-可组合 Composeable:接口
-可重用 Reusable:独立
-可维护 Maintainable:各个组件仅包含自身的逻辑,更容易被理解和维护
-可测试 Testable

例子

Tab 选择器,例子来自于 github 的 react-tab-selector
用 jQuery 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<div id="container"></div>
<script>
var data = [
{name:'Red', value:'red'},
{name:'Blue', value:'blue'},
{name:'Yellow', value:'yellow'},
{name:'Green', value:'green'},
{name:'White', value:'white'}
];
$.fn.TabSelector = function(options){
var arr = ['<div class="tab-selector">'];
arr.push('<label>', options.label, '</label>'); //?? 用个模板or结构化的东东还是有必要的
arr.push('<ul>');
options.data.forEach(function(item){
arr.push('<li data-value="', item.value ,'">'); //?? 为什么不一次性push呢
arr.push(item.name);
arr.push('</li>');
});
arr.push('</ul></div>');
this.html(arr.join(''));
var lastSelected = null; //?? 好处是
//插入dom后才能绑定事件哦~
this.on('click', 'li', function(){
var me = $(this);
lastSelected && lastSelected.removeClass('selected');
me.addClass('selected');
lastSelected = me;
});
return this;
};
$('#container').TabSelector({
label: 'Color',
data: data,
selected: null
});
</script>

用 React 实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<div id="container"></div>
<!-- 注意:type="text/jsx" -->
<script type="text/jsx">
var data = [
{name:'Red', value:'red'},
{name:'Blue', value:'blue'},
{name:'Yellow', value:'yellow'},
{name:'Green', value:'green'},
{name:'White', value:'white'}
];
var TabSelector = React.createClass({
getInitialState: function(){
return {
selected: this.props.selected
};
},
handleOnClick: function(e){
this.setState({
'selected': e.target.getAttribute('data-value')
});
},
render: function(){
var tabs = this.props.data.map( function(item){
var selected = item.value==this.state.selected?'selected':'';
return <li data-value={item.value}
className={selected}
onClick={this.handleOnClick}
>{item.name}</li>
;
}, this);
return <div className="tab-selector">
<label>{this.props.label}</label>
<ul>{tabs}</ul>
</div>
;
}
});
React.render(TabSelector({
label: 'Color',
data: data,
selected: null
}), document.getElementById('container'));
</script>

对比下:
用 jQuery 构建插件:
1.需要构建第一次 render 出来的 DOM 结构
2.需要知道如何切换 UI 上的选中状态

而 React:
1.仅需要考虑整体界面的 DOM 构建
不要关心布局的更新啦,每次调用组件的 setState() 方法,直接触发React的render来重建整个界面

这,就是简化 UI 逻辑带来的好处。

其他概念

点击查看另一篇博客短文 React 的其他概念
1.单向的数据流动 Flux
2.只读数据
3.直观的编程方式 JSX
4.React 思想的延伸

小结

React 是为了解决前端开发中的真正问题而产生的。它是一个全新思路的前端 UI 框架,完全接管了 UI 开发中最复杂的局部更新部分(擅长于数据不断变化的大型应用程序)、引入了基于组件的开发思想(从另个角度来审视UI的构成),提高了开发效率,让代码更容易理解、维护和测试。

参考

系列:http://www.infoq.com/cn/dive-into-react
入门:http://www.infoq.com/cn/articles/subversion-front-end-ui-development-framework-react
视频:https://www.youtube.com/watch?v=KVZ-P-ZI6W4#t=533

?? 传说,性能很好
?? 不同项目-有自己的问题,就应该有自己的一个
?? 咳咳,如何进行高性能的复杂DOM操作

文章目录
  1. 1. 简介
  2. 2. React 原理
    1. 2.1. 虚拟 DOM
    2. 2.2. 简化的组件模型
    3. 2.3. 例子
  3. 3. 其他概念
  4. 4. 小结
  5. 5. 参考