通过前面一章的学习,我们已经了解了有关 React 的基本信息,以及它是如何帮助我们轻松创建即使是最复杂的用户界面。但是对于 React 提供的所有精彩来说,刚开始学习它可不是最简单的事情。React 的学习曲线相当陡峭,里面大大小小的障碍不少。
本章会从创建一个简单的 React 应用开始。在学习中,会直接遇到一些障碍,有些障碍我们现在姑且略过。在本教程末尾,我们不仅可以创建一些可以骄傲地展示给朋友和家人看的东西,还可以为后面的教程中 深入 React 打下良好的基础。
处理 JSX
在开始创建应用程序之前,我们首先要搞定一项重要的事情。React 与我们曾经用过的很多 JavaScript 库不一样。在用其它 JS 库时,大多数时候你只需要用一个 script 标记引用已经用该 JS 库写好的代码就可以了。但是在 React 中不行,我们必须先搞清楚 React 应用创建的机制。
我们知道,Web 应用(以及浏览器显示的其它一切)是由 HTML、CSS 和 JavaScript 组成的:
不管我们的 Web 应用是用 React, 还是 Angular、Knockout、jQuery 这些库写的,最终的结果都是 HTML、CSS 和 JavaScript 的组合。否则,浏览器是不知道要做什么的。
现在,这里就是 React 的特殊性出现的地方。除了标准的 HTML、CSS 和 JavaScript 外,很多 React 代码都会用 JSX 编写。JSX 是一门可以让我们很容易混合 JavaScript 和 类似 HTML 的标记,来定义用户界面元素以及其功能的语言。这听起来很酷,但是问题是:浏览器是不知道如何处理 JSX的。
要用 React 创建 Web 应用,我们需要一种方式采用 JSX,并将它转换为浏览器可以理解的标准 JavaScript:
如果不这么做,React 应用就无法运行。目前将 JSX 转换为 JavaScript 有两种解决方案:
围绕 Node 以及一些构建工具(比如 Webpack)来设置开发环境。在这种环境中,每次执行构建时,所有 JSX 被自动转换为 JS,放在磁盘上,让我们可以像标准 JavaScript 文件一样引用。
让浏览器在运行时自动将 JSX 转换为 JavaScript。我们直接像 JavaScript 一样用 JSX,浏览器负责剩下的转换。
这两种解决方案都有一席之地,我们来看看各自的影响。
第一种解决方案,虽然开始有点复杂,有点费时,但是是当今现代 Web 开发的方式。除了把 JSX 编译(更精确的说是转译)为 JS 外,这种方法允许我们利用模块、更好的构建工具,以及让创建复杂 Web 应用变得稍微可管理的很多其它特征。
第二种解决方案提供了一种快速而直接的路径,开始花更多时间写代码,更少时间花在开发环境上。要用这个解决方案,我们要做的就是引用一个脚本文件。这个脚本文件负责在页面加载时,将 JSX 转换为 JS,然后我们的 React 应用就开始活起来,这样就不需要折腾开发环境。
在 React 入门阶段,我们打算用第二种方案。那么为什么我们不一直用第二种方案呢?原因是,浏览器每次要花时间把 JSX 翻译为 JS,这对性能是有影响的。在学习如何使用 React 时,这是完全可以接受的,但是在部署应用程序实际使用时,这肯定是完全不能接受的。所以后面我们会在已经熟悉了 React 后,再用第一解决方案,即设置开发环境。
上手 React
在前一节,我们看到两种让浏览器可以理解 React 的方式。在本节中,我们要付诸于实践。首先,我们需要一个空白 HTML 页面作为起点。
如果你手边没有一个空白 HTML 页面,那就用下面的好了:
React! React! React!然后在 title 标记后添加如下两行:
第一行引入 核心 React 库,第二行引入 React DOM 库。如果没有这两个库,我们是没法创建 React 应用的。然后,我们还需要在两个 script 标记下添加对 Babel JavaScript 编译器的引用:
Babel 可以做很多很酷的事情,但是我们关心的是将 JSX 变成 JavaScript 的能力。
此时,我们的 HTML 页面应该是这样的:
React! React! React!现在如果马上预览页面,我们会注意到页面是空的,什么都看不到。没关系,下面我们就要让它显示点什么。
显示你的姓名
你要做的第一件事情就是在屏幕上显示你的姓名。实现的方式是用 render 方法。在 script 标记内,添加如下代码:
ReactDOM.render(
Sherlock Holmes,
document.body
);
此时,不要担心这几行代码到底是什么意思。我们的目标是先在屏幕上显示点什么,不久之后我们就会搞清楚这几行代码到底在做什么。现在,在预览页面看看发生了什么之前,我们需要给这个 script 块标注一下,这样 babel 才能可以发挥其魔力。实现方法是将 script 标记的 type 属性设置为 text/babel:
ReactDOM.render(
Sherlock Holmes,
document.body
);
之后,我们就可以在浏览器预览了。我们会看到单词 'Sherlock Holmes' 在屏幕上用很大的字符打印出来。恭喜!你刚用 React 创建一个 APP。
这玩意很显然是不那么让人激动的。但是它给你引入了在 React 领域最频繁使用的方法之一:render 方法。
render 方法带有两个参数:
你想输出的像 HTML 一样的元素,即 JSX
React 将要在 DOM 中渲染 JSX 的位置
如下是我们的 render 方法的样子:
ReactDOM.render(
Sherlock Holmes,
document.body
);
这里,第一个参数是封装有文本 “ Sherlock Holmes” 的 h1 标记。这个在 JavaScript 内,类 HTML 的语法就是 JSX。在我们在后面将会花大量时间深入研究 JSX 之时,我应该先提到:它看起来一样疯狂。每当在JavaScript 中看到括号和斜线,我就心死了,因为我得处理字符串转义和引号这些破玩意。而用 JSX,这些都不需要我做了。
第二个参数是 document.body。这个参数没啥特别的,它只是指定 JSX 应该挂在 DOM 中的哪个位置。在我们的示例中,当 render 方法运行时, h1 标记以及它内部的所有东西都放在文档 body 元素内。
我们这个练习的目的是在屏幕上显示你自己的名字,好吧,继续,把代码修改一下让它显示你的名字。对于我自己来说,render 方法看起来是如下的样子:
ReactDOM.render(
Batman,
document.body
);
好吧,如果我们的名字是 Batman(蝙蝠侠),那么该方法就是这样的。不管怎样,如果现在预览你的页面,你会看到显示出来的是你的名字,而不是 Sherlock Holmes.
所有这一切依然是熟悉的
虽然上面的 JavaScript 因为有了 JSX 而看起来很新奇,但是你在浏览器中看到的最终结果依然是漂亮干净的 HTML、CSS 和 JavaScript。要亲自看到这些,下面我们来对应用程序的行为和外观做点修改。
改变输出的目标
我们要做的第一件事情是改变 JSX 输出的目标。用 JavaScript 将输出直接放在 body 元素上肯定不是一个好主意。有时候会出错,特别是如果你将 React 与其它 JS 库和框架混合在一起用时。推荐的路径是专门创建一个元素作为新的根元素,让这个新元素作为 render 方法要用的目标。OK,我们回到 HTML,添加一个 id 值为 container 的 div 元素。
没有必要为了这一个小变动把所有 HTML 展示出来,这里我们只展示 body 元素的样子:
ReactDOM.render(
document.body
);
这里 container div 元素已经安全定义过了,下面我们修改 render 方法,用这个 div 元素替换 document.body。如下是替换的方法之一:
ReactDOM.render(
Batman,document.querySelector("#container")
);
另一个方法是在 render 方法之外做点事情:
var destination = document.querySelector("#container");
ReactDOM.render(
Batman,
destination
);
注意 destination 变量存储了对 container DOM 元素的引用。在 render 方法内,我们只是引用了相同的 destination 变量,而不是用一个完整的元素查找语法作为参数。我这样做的原因很简单:我想展示的是你依然在写 JavaScript,而 render 只是另一个烦人的带有两个参数的旧方法。
给元素加上样式
在说今天就到这里吧之前,我们来做最后的修改。现在,我们的姓名是以浏览器提供的默认的 h1 样式显示,这太丑了。下面我们添加一些 CSS 让它好看点。在 head 标记内,添加如下 CSS 样式:
#container {
padding: 50px;
background-color: #EEE;
}
#container h1 {
font-size: 48px;
font-family: sans-serif;
color: #0080a8;
}
添加完这些样式后,预览一下页面。你可以看到文本比以前要好看多了:
CSS 起作用的原因是,在运行所有 React 代码后, DOM 的 body 包含了 container 元素,该元素内有一个 h1 标记。h1 标记是完全用 JSX 语法在 JavaScript 内定义,还是用 CSS 定义在 render 方法外,完全无所谓。你的 React 应用的最终结果依然 100% 的 HTML、CSS 和 JavaScript:
React! React! React!#container {
padding: 50px;
background-color: #EEE;
}
#container h1 {
font-size: 144px;
font-family: sans-serif;
color: #0080a8;
}
var destination = document.querySelector("#container");
ReactDOM.render(React.createElement(
"h1",
null,
"Batman"
), destination);
我们可以看到,这里连一点 React 类似代码的痕迹都看不到。
总结
如果这是你第一次创建 React 应用,那么这里已经涵盖了很多基础知识。最大的亮点之一是 React 与其它库是不同的,因为它使用全新的 JSX 语言定义 UI。JSX 的影响不仅仅是定义 UI 元素,它还完全改变了创建应用程序的方式。因为浏览器不能理解 JSX,你需要使用一个中间步骤将 JSX 转换为 JavaScript。一种方式是创建应用来生成与 JSX 源代码相关的转译了的 JavaScript 输出。另一种方式(即我们在这里用的)是在浏览器本身上用 Babel 库来将 JSX 翻译为 JavaScript。虽然在生产环境中因为性能的原因我们不推荐这样做,但是在刚开始学习 React 时候,这样做很方便。
在后续教程中,我们会花一些时间深入了解 JSX,并且超越 render 方法,了解 让 React 运行的所有重要的事情。
React初学者系列教程