Leveling Up With React: React Router
BRAD WESTFALL // MARCH 14, 2016
Link: https://css-tricks.com/learni...
When I was first learning, I found lots of beginner guides (i.e. 1, 2, 3, 4) that showed how to make single components and render them to the DOM. They did a fine job of teaching the basics like JSX and props, but I struggled with figuring out how React works in the bigger picture -- like a real-world Single Page Application (SPA). Since this series covers a lot of material, it will not cover the absolute beginner concepts. Instead, it will start with the assumption that you already understand how to create and render at least one component.
当初我学习的时候,我找到很多入门指南(第1步、第2步、第3步……)手把手地教你如果写一个个组件,又如何把它们渲染到DOM中。虽然这些教程很多第介绍了基本概念,比如什么是JSX,什么是props等等,但我还是很困惑,困惑如何在一个真实一点的项目中使用React——比如做一个真正的单页面应用(SPA)。由于这系列文章要涵盖很多内容,所以我们不再累述初学者概念,而是假设你已经具备如何构建和渲染组件的基本知识。
For what it's worth, here are some other great guides that aim at beginner:
Series Code
This series also comes with some code to play with at GitHub. Throughout the series, we'll be building a basic SPA focused around users and widgets.
这系列文章还附带了一些代码放在GitHub上。通过这个系列教程,我们将会一起构建一个基于用户和小部件的基本SPA。
To keep things simple and brief, the examples in this series will start by assuming that React and React Router are retrieved from a CDN. So you won't see require() or import in the immediate example below. Towards the end of this tutorial though, we'll introduce Webpack and Babel for the GitHub guides. at that point, it's all ES6!
简洁起见,咱们这系列的范例代码是假设你的React和React Router是通过CDN获取的,所以,在接下来的范例代码中,你看不到require()或import这样的语句。在本教程结束的时候,我们将会结束Webpack和Babel的GitHub指南。到那时,都用ES6语法来写。
React-Router
React isn't a framework, it's a library. Therefore, it doesn't solve all an application's needs. It does a great job at creating components and providing a system for managing state, but creating a more complex SPA will require a supporting cast. The first that we'll look at is React Router.
大伙们都知道,React不是一个框架,只是一个工具库。因此,它没办法解决一个应用的所有需求。React可以很好地构建组件和管理状态,但如果要构建一个较复杂SPA,我们需要一些“外援”。第一个我们将要介绍的是React Router。
If you've used any front-end router before, many of these concepts will be familiar. But unlike any other router I've used before, React Router uses JSX, which might look a little strange at first.
如果你以前用过其它的前端路由工具,那这里的很多概念你都不会陌生。但跟我以前用过的其它路由工具不同的是,React Router使用JSX,一开始看上去可能有一点点怪。
As a primer, this is what it's like to render a single component:
首先,渲染一个简单的组件应该是这样的:
var Home = React.createClass({
render: function() {
return (<h1>Welcome to the Home Page</h1>);
}
});
ReactDOM.render((
<Home />
), document.getElementById('root'));
Here's how the Home component would be rendered with React Router:
但如果用React Router来渲染这个Home组件,应该是下面这样的:
...
ReactDOM.render((
<Router>
<Route path="/" component={Home} />
</Router>
), document.getElementById('root'));
Note that <Router> and <Route> are tow different things. They are technically React components, but they don't actually create DOM themselves. While it may look the <Router> itself is being rendered to the 'root', we're actually just defining rules about how our application works. Moving forward, you'll see ths concept often: components sometimes exist not to create DOM themselves, but to coordinate other components that do.
要注意,这里的<Router>和<Route>是两个不同的东西。从技术上说,它们都是React组件,但它们不会真地创建DOM节点。虽然看起来像是<Router>自身被渲染到'root'根节点上,但实际上,我们只是定义了我们的应用如何工作的规则而已。在接下来的教程里,你会经常遇到这个概念:有的组件它存在的意思不在为了渲染DOM,而是协助其它组件渲染DOM。
In the example, the <Route> defines a rule where visiting the home page / will render the Home component into the 'root'.
在这个例子中,<Route>定义这样一个规则:当访问首页/时,将渲染Home组件到'root'根节点上。
Multiple Routes
In the previous example, the single route is very simple. It doesn't give us much value since we already had the ability to render the Home component without the router being involved.
在上面这个例子中,单一路由非常简单。但对于咱们没有价值,因为即使我们不用router,也能够将Home组件渲染到页面中。
React Router's power comes in when we use multiple routes to define which component should render based on which path is currently active:
React Router的作用在于我们可以通过多个route实现浏览器根据当前的url路径,渲染对应的组件:
ReactDOM.render((
<Router>
<Route path="/" component={Home} />
<Route path="/users" component={Users} />
<Route path="/widgets" component={Widgets} />
</Router>
), document.getElementById('root'));
Each <Route> will render its respective component when its path matches the URL. Only one of these three components will be rendered into the 'root' at any given time. With this strategy, we mount the router to the DOM 'root' once, then the router swap components in and out with route changes.
当URL与某个Route的path匹配时,这个Route对应的组件就会被渲染。在任何的时候,就有上面这几个组件会被渲染到根节点root上。有了这个策略,一旦我们往'root'根节点挂载这个Rooter,它就会根据路由的变化而切换组件。
It's also worth noting that the router will switch routes without making requests to the server, so imagine that each component could be a whole new page.
另外要注意的是,route之间的切换,是不需要向后端服务发出请求的,所以,想象下每个组件可能是一个全新页面。
Re-usable Layout
We're starting to see the humble beginnings of a Single Page Application. However, it still doesn't solve real-world problems. Sure, we could build the three components to be full HTML pages, but what about code re-use? Chances are, these three components share common assets like a header and sidebar, so how do we prevent HTML repetition in each component?
我们开始看见一个单页面应用的雏形,但它依然没法解决一些实际问题。当然,我们可以将这个三个组件构建成三个完整的页面,但代码复用何在了?而实际中这个三个组件很可能有着共同的资源,比如头部和侧边栏等,所以如何防止每个组件中的HTML重复了?
Let's imagine we were building a web app that resembled this mockup:
假设我们要构建一个类似下面这样子的网络应用:
When you start to think about how this mockup can be broken down into reusable section, you might end up with this idea:
当你开始思考这个模型如何拆解成可重用的部件,你也许会得出下面的结果:
Thinking in terms of nestable components and layouts will allow us to create resuable parts.
试想一下,嵌套的组件和布局都应该被构建成可重用的部分。
Suddenly, the art department lets you know that the app needs a pager for searching widgets which resembles the page for searching users. With User List and Widget List both requiring the same "look" for their search page, the idea to have Search Layout as a separate component makes even more sense now:
突然,设计部门告诉你这个应用需要一个搜索小工具的页面,类似于用户搜索页面。由于用户列表和小工具列表长得很像,所以将搜索布局作为一个独立的组件开发是有意义的。
Search Layout can be a parent template for all kinds of search pages now. And while some pages might need Search Layout, others can directly use Main Layout without it:
现在,搜索布局可以作为各种搜索页页面的父模板,即使有的页面需要搜索布局,有的不需要搜索布局,而是直接嵌入主布局。
(待续。。。)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。