秦小

React 快速入门指南: ES6 版(译)

这篇文章翻译自 Jack Callister 的 The React Quick Start Guide: ES6 Edition

这篇文章是原文 React 快速入门指南 的 ES6 版。Babel 是一个 Javascript 编译器,加上 React 可以让你写出现代的,可理解的,可维护的用户界面代码。只要知道这些就足以让你开始玩 React 了。跟着这个仓库 starter kit(里面有指导)一起编码吧,或者只是读一读也是好的。

概念(Concepts)

React 只有一个极小的 API. 这使得它用起来好玩,学起来简单,理解起来容易。但是,简单并不意味着熟悉。开始之前,还有少量概念需要了解。来,一个一个看看吧。

React 元素 (React elments) 是表示 HTML 元素的 Javascript 对象。它们不会出现在浏览器中。它们表示浏览器中得 h1, divsection 这样的元素。

组件 (Components) 是开发者创建的 React 元素。它们是用户界面中较大的组成部分,组件中包含结构和功能。比如 NavBar, LikeButton 或者 ImageUploader

JSX 是创建 React 元素和 React 组件的技术。例如 <h1>Hello</hell> 就是一个 JSX 写成的 React 元素。这个 React 元素也可以写成 Javascript 的形式: React.DOM.h1(null, 'Hello');。相较而言 JSX 更好读更好写。 JSX 要先转换成 Javascript 之后才会在浏览器中运行。

虚拟 DOM (The Virtual DOM) 是 React 元素和组件的 Javascript 树。React 将虚拟 DOM 渲染到浏览器,从而显示用户界面。React 监听虚拟 DOM 的变化自动的改变浏览器 DOM 来同步两个 DOM。

我们已经简单了解了这些概念,可以开始使用 React 了。我们创建了一系列的用户界面,每一个都在前一个的基础上添加功能。我们最终创建了一个类似 instagram 的照片流 — 作为一个例子应用程序再好不过了。

渲染(Rendering)

事情的第一步是渲染一个虚拟元素(一个 React 元素或组件)。要记住,因为虚拟元素只存在于 Javascript 内存中,我们必须显式地告诉 React 将它渲染到浏览器 DOM 中去。

1
ReactDOM.render(<img src='http://tinyurl.com/lkevsb9' />, document.getElementById('app'));

见JSBin

代码中的 render 方法接受两个参宿: 一个虚拟元素和一个真实的浏览器 DOM 节点 (node) 。React 将虚拟元素插入到这个 DOM 节点上。现在可以在浏览器上看到图片了。

组件(Components)

组件是 React 的心脏和灵魂。组件是自定义的 React 元素,它们通常扩展了独特的功能和结构。

1
2
3
4
5
6
7
8
class Photo extends React.Component {
render() {
return <img src='http://tinyurl.com/lkevsb9' />
}
}
ReactDOM.render(<Photo />, document.getElementById('app'));

见 JSBin

Photo 类定义为 React 组件类的子类。它有一个 render 返回 React 图片元素的方法。

这个 Photo 组件一 <Photo /> 的形式使用,并且渲染成应用程序的 div

这个组件没有比之前的 React 图片元素做更多的工作,但确实以自定义的功能和结构扩展了。

属性(Props)

属性可以认为是组件的选项。它们以参数的形式传递个组件,看起来就像 HTML 的属性(attributes)一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Photo extends React.Component {
render() {
return (
<div className='photo'>
<img src={this.props.src} />
<span>{this.props.caption}</span>
</div>
)
}
}
ReactDOM.render(<Photo src='http://tinyurl.com/lkevsb9' caption='Hong Kong!' />, document.getElementById('app'));

见 JSBin

在 React 的 render 方法中,传递了两个属性给 Photo 组件:imageURLcaption

在组件的 render 方法中,imageURL 属性用作 React 图片元素的 src, caption 属性用作 React span 元素的文本。

如果一个组件永远不改变其属性,那么就没有意义了,组件的属性是可以改变的。 如果一个组件拥有可变的数据,就会用到状态 (state) 对象。

状态(State)

状态对象是组件内部的。该对象持有的数据随着时间变化。

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
class Photo extends React.Component {
constructor(props) {
super(props);
this.state = {
liked: false
}
}
toggleLiked() {
this.setState({
liked: !this.state.liked
});
}
render() {
const buttonClass = this.state.liked ? 'active' : '';
return (
<div className='photo'>
<img src={this.props.src} />
<div className='bar'>
<button onClick={(e) => {this.toggleLiked(e)}} className={buttonClass}>
</button>
<span>{this.props.caption}</span>
</div>
</div>
)
}
}
ReactDOM.render(<Photo src='http://tinyurl.com/lkevsb9' caption='Hong Kong!' />, document.getElementById('app'));

见 JSBin

拥有状态使组件引入了少量的复杂性。

组件类的 constructor 方法在组件初始化时调用。state 在这个过程中设置。此例中 liked 被设置为 false

注意: 为了 React 准备好渲染的类,super 方法必须要调用(传入 props 参数)。

组件还增加了一个新的方法 toggleLiked。这个新的方法在组件上调用 setState 方法来切换 liked 的值。

组件 render 方法中的变量 buttonClass 根据 liked 的值被设置为 active 或 空值。

buttonClass 在 React 按钮元素当做类名使用。这个按钮还有一个 onClick 事件处理器 toggleLikedonClick 处理器使用了 ES6 的箭头语法,这是 function(e) { return this.toggleLiked(e)} 的简便写法。

下面列出了组件渲染到浏览器 DOM 时发生的事情:

  • 当组件按钮被点击是,toggleLiked 被调用
  • liked 状态改变
  • React 重渲染组件到虚拟 DOM
  • 比较虚拟 DOM 和 之前的虚拟 DOM
  • React 分离出改变的部分并更新到浏览器 DOM

在此例中,React 将改变按钮上得类名。

组合(Composition)

组合就是说将较小的组件合成一个较大的组件。比如 PhotoGaller 组件可以在其内部使用 Photo 组件,想这样:

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class Photo extends React.Component {
constructor(props) {
super(props);
this.state = {
liked: false
}
}
toggleLiked() {
this.setState({
liked: !this.state.liked
});
}
render() {
const buttonClass = this.state.liked ? 'active' : '';
return (
<div className='photo'>
<img src={this.props.src} />
<div className='bar'>
<button onClick={(e) => {this.toggleLiked(e)}} className={buttonClass}>
</button>
<span>{this.props.caption}</span>
</div>
</div>
)
}
}
class PhotoGallery extends React.Component {
render() {
const photos = this.props.photos.map((photo) => {
return <Photo src={photo.url} caption={photo.caption} />
});
return (
<div className='photo-gallery'>
{photos}
</div>
);
}
};
const data = [
{
url: 'http://tinyurl.com/lkevsb9',
caption: 'Hong Kong!'
},
{
url: 'http://tinyurl.com/mxkwh56',
caption: 'Cows'
},
{
url: 'http://tinyurl.com/nc7jv28',
caption: 'Scooters'
}
];
ReactDOM.render(<PhotoGallery photos={data} />, document.getElementById('app'));

见 JSBin

Photo 跟原来的完全一样。

PhotoGallery 组件通过 prop 传入假数据生成了3个 Photo 组件。

总结

这篇文章应该足以让你能够开始使用 React 构建用户界面了。[React docs]详细说明了点点滴滴。强烈建议阅读。

还有一些非常好的视频值得看看。Pete Hunt 关于 React 的演说 re-thinking web application architecture 和 Tom Occhino 对 React Native 的介绍 - 用 React 构建的原生移动端应用 (WIP)。

如果 ES6 你不熟悉,可以查看 Babel 官网的指南,在 REPL 中联系熟悉。

这个指南中没有有关本地环境设置的细节,React 官方文档应该能帮到您,或者查看这个 boilerplate 作为一个简单的解决方案。