React系列之(一) ---入门篇

ReactJS是什么

ReactJS是Facebook内部的一个javascript类库,已于2013年开源,可用于创建WEB用户交互界。它引入了一种新的方式来处理浏览器DOM。那些需要手动更新DOM,费力地记录每一个状态的日子一去不复返了,你只需要声明式的定义各个时间点的用户界面,而无须关心在数据变化时需要更新哪一部份DOM.在任何时间点,ReactJS都能够以最小的DOM修改来更新整个应用程序。

ReactJS的由来

ReactJS发源于Facebook的PHP框架XHP的一个分支,XHP作为一个PHP框架旨在每次有请求进来的时候渲染整个页面,React的产生就是为了把这种重新渲染整个页面的PHP式工作流带到客户端应用中来。

ReactJS的原理

在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因.React为此引入了虚拟DOM的机制,在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。

一个简单的组件

1
2
3
4
5
6
var HelloMessage = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name="John" />, mountNode);

注意是面的代码并不完全是JS, 它使用了JSX语法。

什么是JSX

JSX即javascript XML,一种在reactJS组件内部构建标签的类XML语法。 React在不使用JSX的情况下一样可以工作, 然而使用JSX可以提高组件的可读性, 因此推荐你使用JSX, 在React中使用JSX有以下好处

  • 允许使用熟悉的语法来定义HTML元素树
  • 提供更加语义化且容易懂的标签
  • 程序结构更容易被直观化
  • 抽象了react Element的创建过程
  • 可以随时掌控HTML标签以及生成这些标签的代码
  • 是原生的javascript

举个例子, 在不使用JSX的React程序中创建

1
<div class="title">hello world</div>

这样的HTML结构,可以像这样写

1
React.DOM.div({className:'title'},'hello,world')

或者

1
React.createElement('div',{className:'title'},'hello world');

那么如果用JSX语法, 我们就可以直接这样写了

1
<div className="title">hello world</div>

和我们平时写HTML差不多, 只不过需要注意的是像class,for这些属性因为是JS关键字, 所以需要将class写成className,for写成htmlFor.

一个经典的TODO的例子

angular推出时, 举的就是这个例子, 那么我们现在用React来实现相同的功能看看

根据效果图, 我们可以分析一下, 需要用到哪几个组件, 从外往里看, 最外层得是一个, 比如我们取名TodoApp, 接下来下列表TodoList,列表里的每条数据又是一个, 我们就叫它TodoItem,然后是最下面的用于添加记录的表单, 我们叫它TodoForm。

我们从最里层的TodoItem组件开始写起

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var TodoItem = React.createClass({
getDefaultProps:function(){
return {
checked:false,
text:''
}
},
render:function(){
var oClass = this.props.checked ? 'done-ture': 'done-false';
return (
<li className={oClass}>
<input type="checkbox" checked={this.props.checked} onChange={this.props.change.bind(this,this.props.index)}/>
{this.props.text}
</li>
)

}
});

这里面的onChange处理函数, 是通过this.props.change来引用的父级组件的函数来处理的, 因为在React里一个很重要的思想就是单向数据流, 数据都是从外到内的层层传递, 这样就保证了写组件时的思路清析。

接下是TodoList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var TodoList = React.createClass({
getDefaultProps:function(){
return {
items:[]
}
},
change:function(index){
this.props.change && this.props.change(index); //层层传递
},
render:function(){
var _this = this;
var todoItems = this.props.items.map(function(item,i){
return <TodoItem index={i} checked={item.checked} text={item.text} change={_this.change}/>
});
return (
<ul>
{todoItems}
</ul>
)

}
});

这里的chnage处理函数还是冒泡到了父组件。

然后是TodoForm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var TodoForm = React.createClass({
getInitialState:function(){
return {text:''}
},
onChange:function(e){
this.setState({text: e.target.value});
},
handleSubmit:function(e){
e.preventDefault();
if(this.state.text.trim() === '') return //提交时内容不能为空
this.props.add(this.state.text); //提交时执行父组件的add方法, 并将输入的内容作为参数传递过去
this.setState({text:''});//清空输入框内容

},
render:function(){
return (
<form onSubmit={this.handleSubmit}>
<input onChange={this.onChange} value={this.state.text} />
<input type="submit" value="Add" />
</form>
)

}
});

最后就是TodoApp了

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
var TodoApp = React.createClass({
getInitialState:function(){
return { items:[]}
},
add:function(text){
var items = this.state.items.concat({text:text,checked:false});
this.setState({items:items});
},
change:function(index){
var item = this.state.items[index];
item.checked = !item.checked
this.setState({items:this.state.items});
},
render:function(){
var len = this.state.items.filter(function(item){ return !item.checked }).length;
return (
<div>
<h2>Todo</h2>
<span>{len} of {this.state.items.length} remaining</span>
<TodoList items={this.state.items} change={this.change}/>
<TodoForm add={this.add} />
</div>
)

}
});

完整效果可以看这里, 可能打开的速度有点慢, 耐心等一下, ^_^

在这里处理每条记录的remaining状态, 数据会层层传递到最里层的TodoItem, 这样就保证了数据的流向, 当然如果里层的数据处理
对外层的数据没有影响, 那么就没有必要像这样以冒泡样的传递到顶层组件里, 直接在里层的组件理处理就好了。

整体看起来, 代码好像比我们想像的要多, 但这样做的一个好处就是重复利用起来非常方便,我们可以把这个想像成堆积木,每个组件都是一块最小单元的积木,积木的任意组合,得到任何你想要的形状,组件也是一样。平时我们可以把常用的东西写成组件, 积累到一定的程度的时候, 做应用就是一个快速堆积木的过程了。

如果看完这篇扫盲篇, 发现对react感兴趣的, 可以去官网看一下, 了解更多。
官网地址:http://facebook.github.io/react/

长按关注猫头鹰技术公众号(mtydev)
img

留言

本站总访问量

留言