原文链接: css-tricks.com
本文是 Brad Westfall 编写的 React 系列三篇教程中的第一篇。Brad 将本文投递给我时指出:React 初级教程有很多,但是晋级教程却不多。如果你是 React 新手,我推荐你观看这个介绍视频。本系列教程在这个视频的基础上继续。
系列文章
第一部分: React Router (即本文!)
第二部分: 容器组件
第三部分: Redux
在开始学习 React 时,我找到了很多新手指南(比如 1、2、3、4)。这些教程大多是展示如何创建简单的组件,如何将它们渲染到 DOM。对于教授 JSX 和 props 这种基础知识,这些教程还不错,但是我竭力想搞清楚 React 在更宽的视野上是如何工作的 - 比如实际的单页应用程序(SPA)。因为本系列教程涵盖了很多素材,所以这里我就不讲解完全初学者概念了,而是假定你已经理解了如何创建和渲染至少一个组件。
这里还有一些很好的针对初学者的指南:
React.js and How Does It Fit In With Everything Else?
Rethinking (Industry) Best Practices
React.js Introduction For People Who Know Just Enough jQuery To Get By
本系列相关代码放在 GitHub上。整个系列中,我们将创建一个以用户和组件为焦点的基础 SPA。
为简洁起见,本系列的示例会从假设 React 和 React Router 都是从 CDN 获取的开始。所以你不会在下面的中级示例中看到 require()
或 import
。不过,到本课程结束前,我会引入 Webpack 和 Babel,这时候就都用 ES6了。
React 不是一个框架,而是一个库。因此,它不会解决一个应用程序的所有需求。React 对于创建组件,并在提供管理状态的系统方面做的很好。但是,创建一个更复杂的 SPA 需要一些 配角。这里我们要研究的就是配角之一: React Router.
如果以前你曾经用过任何前端路由器,那么应该已经熟悉了很多概念。但是 React Router 与我以前曾经用过的任何其它路由器都不同,它用 JSX,这玩意开始看起来会有点奇怪。
作为入门,如下是如何渲染一个组件的示例代码:
var Home = React.createClass({
render: function() {
return (Welcome to the Home Pageh1>);
}
});
ReactDOM.render((
), document.getElementById('root'));
如下是 Home
组件用 React Router 是如何渲染的:
...
ReactDOM.render((
Router>
), document.getElementById('root'));
注意,这里 和
是两个不同的东西。从技术上讲,二者都是 React 组件,但是它们自己实际上都不会创建 DOM。看起来好像
本身被渲染为
'root'
,但是实际上我们只是定义应用程序如何工作的规则。继续下去的话,你会经常看到这个概念:组件有时候并非为自己创建为 DOM 而存在,而是协调创建 DOM 的其它组件。
在本例中, 定义了一个规则:访问主页(
/)
的地方,会渲染 Home
组件为 'root'
。
前面的示例中,只有一个路由,这很简单。它并没有给我们更多的价值,因为我们不用路由器就可以渲染 Home
组件。React Router 的强大来自于:我们可以使用多个路由来定义根据当前活动的路径渲染哪个组件。
ReactDOM.render((
Router>
), document.getElementById('root'));
当 路径(path)匹配 URL 时,每个 会渲染各自的组件。这三个组件中只有一个会在任何给定时间渲染到
'root'
中。使用这种策略,我们一次就把路由器挂载到 DOM 的 'root'
上,然后路由器就根据路径改变切换组件的进出。
还要指出的是,路由器不用向服务器发起请求就会切换路由,所以可以把每个组件假想为一个完整的新页面。
我们现在看到的是单页应用程序最寒碜的开始。但是,它依然不能解决实际的问题。确实,你可以创建这三个组件来组成完整的 HTML 页面,但是要代码重用该怎么办?机会是,这三个组件共享相同的部件,比如 header 和 sidebar,所以我们如何防止每个组件中的 HTML 重复呢?
假设我们正在创建一个由如下界面原型组成的 Web 应用程序:
一个简单的网站原型
当你开始思考如何将这个原型分拆成可重用的部分时候,最后你可能会有如下的分拆:
将一个简单的 Web 原型分成多个部分
考虑在嵌套组件和布局方面会让我们创建可重用的部分。
突然,设计部门让你知道应用程序需要需要一个搜索部件页,该页由搜索用户页面组成。User List 和 Widget List 都需要搜索页面有相同的外观,那么现在将 Search Layout 作为一个单独的组件就更有意义:
搜索组件取代搜索用户页,但是父界面部分不变
Search Layout 现在可以是所有搜索页面类型的父模板。并且在一些页面需要 Search Layout 的同时,其他的页面可以直接使用 Main Layout ,而不需要 Search Layout:
解耦了的布局
这是一种常见的策略,如果用过任何模板系统,你可能也做过很相似的事情。现在我们开始写 HTML。开始我们只写静态的 HTML,不用考虑 JavaScript: