React文档翻译 - QuickStart

React 文档翻译

安装

React非常的灵活,你可以在许多项目中都使用它。你可以利用它创建新的app,你也可以逐渐地将它引入一个已有的代码库,而不用进行重写。

以下是一些我们开始的途径:

  • 尝试React
  • 创建一个新的App
  • 将React加入现有的App

尝试React

如果你只是想随便玩玩React,那么你可以使用CodePen,你可以尝试以这个简单的Hello World小程序作为开始。你不需要安装任何东西,直接试着修改它,看看运行结果就行了。


创建一个新的App

Create React App是创建一个新的React单页应用的最好的方式。它可以帮你搭建你的开发环境,这样你就可以使用那些最新的Javascript特性了。它提供了非常棒的开发体验,并且会优化你的最终生产版本。
PS: 你需要安装Node.js,并且版本>=6。

1
2
3
4
5
npm install -g create-react-app
create-react-app my-app
cd my-app
npm start

Create React App并不处理后端逻辑或者数据库,它仅仅创建了一个前端的构建pipeline,所以你可以结合任何的后端技术来使用它。它在底层使用了Babel以及Webpack这样的构建工具,但是并不需要你做任何额外的配置。

当你准备好将App部署到生产环境时,你可以运行npm run build来在build文件夹中创建一个优化过的版本。你可以通过以下链接学习更多关于Create React App的知识:

  1. 官方文档
  2. 用户指南

将React加入现有的App

要开始使用React,你不必重写你的应用程序。

我们建议将React加入到你的应用的某个小部分中去,例如一个独立的小控件,这样你可以知道它是否能很好的配合你的应用。

虽然React可以脱离build pipeline而使用,但是我们强烈推荐你能搭建这样一个环境,这会使你变得更加高效。如今典型的build pipeline包含了以下的几个部分:

  • 包管理器(package manager): 例如Yarn或者npm,它使得你可以使用大量同生态圈的第三方的包,并且可以轻松地对它们进行安装或升级。
  • 模块打包器(bundler): 例如webpack或者Browserify,它使你可以写出模块化的代码,并且将它们整合到一个个小的包中去,来优化载入时间。
  • 编译器(compiler): 例如Babel,它使得你写的最新的Javascript也能运行在旧的浏览器上。

安装Rea

我们推荐使用Yarn或者npm来管理前端的依赖。如果你刚刚接触包管理器,那么Yarn的文档将会是一个比较好的学习材料。

要使用Yarn安装React,执行以下命令:

1
2
yarn init
yarn add react react-dom

要使用npm安装React,执行以下命令:

1
2
npm init
npm install --save react react-dom

PS: Yarn和npm都是从npm的网站那里下载包的。

激活ES6以及JSX

我们推荐结合Babel使用React,这使得你可以在Javascript代码中使用ES6以及JSX。ES6是一套新的Javascript标准,它使得开发更加简洁。JSX是Javascript一个扩展,它可以与React配合的非常完美。

Babel安装说明解释了如何在不同的构建环境中配置Babel,你需要确保你安装了babel-preset-react以及babel-preset-env,并且在你的.babelrc配置文件中激活了它们,这样你就可以继续了。

使用ES6和JSX的Hello World

我们推荐你使用webpack或者Browserify,这样你可以写出模块化的代码,并且将它们整合到一个个小的包中去,来优化载入时间。

最简单的React例子就像这样:

1
2
3
4
5
6
7
import React from 'react';
import ReactDom from 'react-dom';
ReactDom.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);

这段代码渲染了一个id为root的DOM元素,所以你需要在你的HTML文件某处添加这样的一行代码: <div id="root"></div>

相似地,你也可以使用React渲染你使用其他Javascript UI库写的现有App中的DOM元素。

开发版本与生产版本

默认情况下,React包含了许多有用的警告。这些警告在开发过程中十分有用。

但是,它们使得React的开发版本(development version)过大也过慢,所以在部署时,你需要使用生产版本(production version)。

了解如何辨别你的网站正使用正确版本的React,并且通过以下途径有效地配置生产build过程:

使用CDN

如果你不想要使用npm来管理客户端的包,reactreact-dom也提供了CDN的版本:

1
2
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

上面的版本是用来为开发服务的,并不适合生产版本,简化并优化过的版本可以通过以下链接获得:

1
2
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

如果需要加载特定版本的reactreact-dom,可以用版本号替换掉链接中的16

如果你是使用Bower的,那么React可以通过react包获得。

为什么需要crossorigin属性?

如果你通过CDN来使用React,那么我们推荐你将crossorigin属性按照如下设置:

1
<script crossorigin src="..."></script>

我们也推荐你检验你所使用的CDN设置了Access-Control-Allow-Origin: *的HTTP header:

这使得你在使用React 16或以后的版本的时候会有一个更好的错误处理的体验。

Hello World

开始学习React的最简单的方法就是使用我们在CodePen上给出的这个Hello World Example。你不需要安装任何东西,你只要在另一个标签页中打开它,并且跟着我们一起研究这个例子就可以了。如果你还是想使用一个本地的开发环境,请查看上一章的具体内容。

最简单的React example就像下面这样👇:

1
2
3
4
ReactDom.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);

这段代码渲染了一个内容为“Hello, world!”的标题。

接下来的几个部分将逐渐地引导你开始使用React。我们将会深入研究React应用的基础构建单元: 元素(elements)和组件(components)。一旦你掌握了它们,你就可以使用这些可复用的小“砖瓦”来构建复杂的应用程序了。


关于Javascript的小提示

React是一个Javascript库,所以这假设你对Javascript语言有一个基本的理解。如果你感觉自己并不是那么自信,那么你可以参考这个教程,这样你就可以更轻松地跟上我们的节奏了。

我们也将在例子中使用一些ES6语句,我们会试着用保守一点的方式去使用它,因为它相对来说还是比较新的,但是我们鼓励你熟悉一下这些知识: 箭头函数模板字符串letconst

JSX简介

观察下面的变量声明方式:

1
const element = <h1>Hello, world!</h1>;

这个有趣的标签既不是字符串也不是HTML。

这样的语句叫做JSX,是Javascript的一个句法扩展。我们推荐结合React使用它来描述UI应该呈现的样子。JSX也许会让你联想到一个模板语言,不过它是拥有完整的Javascript功能的。

JSX产生了React “elements”,我们将会在下一节探索它们是如何被渲染为DOM的。下面的内容,可以让你学到JSX的基础知识,让你快速起步。

在JSX中嵌入表达式

你可以通过将代码包裹在花括号内,在JSX中嵌入任何的Javascript表达式。

比方说,2+2user.firstName,或者formatName(user)都是有效的表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}
const user = {
firstName: 'Louis',
lastName: 'Melo'
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
ReactDOM.render(
element,
document.getElementById('root')
);

我们将JSX分成了好几行来提高了它的可阅读性。虽然这不是必要的,但是当这样做的时候,我们也推荐你使用括号将它包裹住,防止 自动补全分号 的陷阱。

JSX也是一个表达式

在编译过后,JSX表达式会变成正常的Javascript对象。

这意味着,你可以在if语句以及for循环中使用JSX,并可以将它赋值给变量,将它作为参数接收,也可以通过方法返回它:

1
2
3
4
5
6
function getGreeting(user) {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}

使用JSX声明属性

你可以使用引号来将字符文字声明为属性:

1
const element = <div tabIndex="0"></div>;

你也可以使用花括号来嵌入Javascript表达式作为属性:

1
const element = <img src={user.avatarUrl}></img>;

在使用Javascript表达式和花括号作为属性的时候,不要再添加引号。你应该使用这二者的其一,而不是同时使用它们两个。

使用JSX声明子节点(children)

如果一个标签是空标签,你可以直接以/>作为结尾:

1
const element = <img src={user.avatarUrl} />;

JSX标签也有可能包含子节点:

1
2
3
4
5
6
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);

JSX防止注入攻击

将用户输入嵌入在JSX是非常安全的:

1
2
3
const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

默认情况下,React DOM在渲染之前就会(???)任何嵌套在JSX中的值,因此它保证了你永远不能注入任何没有在你的应用中显示声明的代码。一切都会在渲染之前被转换成字符串,这也有效阻止了XSS攻击(cross-site-scripting)

JSX意味着对象

Babel将JSX编译为对React.createElement()方法的调用。

下面的这两个例子是完全一致的:

1
2
3
4
5
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
1
2
3
4
5
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);

React.createElement()帮助你执行了一些bug检查,但是更重要的是,它创建了如下的一个对象:

1
2
3
4
5
6
7
8
// 注意:这个结构已被简化
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};

这样的对象被称为“React elements”。你可以将它们认作是对于你想要在屏幕上看到的东西的描述。React会读取这些对象,然后用它们来构建DOM,并且保持它们的状态更新。

我们将在下一节研究如何将React elements渲染到DOM。

Tip:
在Atom编辑器中,可以搜索language-babel来使得编辑器支持对于ES6和JSX的高亮显示。

渲染元素

元素是React Apps的最小构建单元。

一个元素描述了你想要在屏幕上看到的东西:

1
const element = <h1>Hello, world!</h1>;

与浏览器DOM元素不同的是,React elements就是普通的对象,其创建也十分简单。React DOM关心的是更新DOM以匹配React elements。

请注意: 这里有可能会造成与“components”概念的混淆,我们将在下一节介绍components,elements其实是构成components的东西。


将元素渲染进DOM中

假定有一个<div>在你的HTML文件的某处吧:

1
<div id="root"></div>

我们将这个称为一个“root” DOM节点,因为它其中的所有东西都将由React DOM管理。

只用React构建的应用通常只有一个单一的根DOM节点。如果你是将React整合进一个已有的app,那么你可以有任意多个隔离的根DOM节点。

要渲染一个React element为一个根DOM节点,需要将两者都传递给ReactDOM.render()方法:

1
2
3
4
5
const element = <h1>Hello, world</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);

更新被渲染的元素

React elements是无法修改的(immutable)。一旦你创建了一个元素,你就不能改变它的子节点或是属性。一个元素就像一部电影里的单独一帧: 它代表了某个特定时间点的用户界面。

根据我们到目前为止学到的知识,更新用户界面的唯一方法是: 创建一个新的元素并将它传递给ReactDOM.render()方法。

思考下面这个时钟的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function tick() {
const element = (
<div>
<h1>Hello, world!</h1>
<h2>It is {new Date().toLocaleTimeString()}.</h2>
</div>
);
ReactDOM.render(
element,
document.getElementById('root')
);
}
setInterval(tick, 1000);

每隔一秒钟,setInterval()的回调方法就会调用一次ReactDOM.render()方法。

注意,在实践中,大多数的React apps都只调用一次ReactDOM.render()方法,在下一节我们将会学习这些代码是如何被封装(encapsulated)到有状态的components中去的。


React只会进行有必要的更新

React DOM会将元素及其子节点与之前的相比较,并且只会对DOM进行有必要的更新,将DOM变到所需要的状态。

这一点,你可以从上一个例子中看出来,利用浏览器工具,尽管我们每隔一秒都创建一个描述整个UI树的元素,但是只有内容因更新DOM而发生改变的文本节点发生了变化。

根据我们的经验,相比于思考如何随着时间改变UI,思考在给定时刻UI所要呈现的样子会消除非常多的bug。

Components and Props

Components使你能够将UI分成独立且可重复利用的小块,并且独立地思考每一小块UI。

从概念上讲,components就像是JavaScript中的方法,它们能够接受任意的输入(这里被称为props),并且返回描述了在屏幕上呈现何物的React elements。


Functional and Class Components

定义一个component的最简单的方法就是编写一个Javascript方法:

1
2
3
function Welcome(props){
retrun <h1>Hello, {props.name}</h1>;
}

这个方法就是一个有效的React component,因为它接受了一个单独的props,并且返回了一个React element,我们将这种组件叫做方法性组件(functional components),因为它在字面上就是一个JavaScript方法。

你也可以使用一个ES6 Class来顶一个component:

1
2
3
4
5
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

从React的视角来看,以上的两个components是同等的。

Classes具有一些额外的特性,我们将在下一章进行讨论。在那之前,我们将使用functional components,因为它比较简单明了。


Rendering a component

之前,我们只碰到过表示DOM标签的React elements:

1
const element = <div />;

然而,elements也可以表示用户定义的components:

1
const element = <Welcome name="Snow" />;

当React见到一个表示用户定义的componet的element时,它就将JSX的属性以一个单独的对象传递给这个component,我们将这个对象叫做props。

举个例子,这段代码将会打印 Hello, snow:

1
2
3
4
5
6
7
8
9
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="snow" />;
ReactDOM.render(
element,
document.getElementById('root')
);

让我们重新看一下这个例子中发生了什么:

  1. 我们使用 <Welcome name="snow" /> 这个元素,调用了 ReactDOM.render() 方法
  2. React以 {name: 'snow'} 作为props,调用了 Welcome 组件
  3. 我们的 Welcome 组件返回了 <h1>Hello, snow</h1> 元素作为结果
  4. ReactDOM快速地更新了DOM