本文同步自个人博客 Reeoo's Blog,欢迎移步前往,^_^html
本文基于
React Router v1.03
版本。react
React Router
是一个为React
设计的强大的路由库。能够帮助咱们快速的实现路由功能,包括URL
和React components
之间的同步映射关系。
在解释React Router
如何使用以前,咱们先来看看在不使用React Router
的状况下,是怎么样的,接下来的全部例子中都将使用ES2015
语法和语言特性。浏览器
React Router
import React from 'react' import { render } from 'react-dom' const About = React.createClass({/*...*/}) const Inbox = React.createClass({/*...*/}) const Home = React.createClass({/*...*/}) const App = React.createClass({ getInitialState() { return { route: window.location.hash.substr(1) } }, componentDidMount() { window.addEventListener('hashchange', () => { this.setState({ route: window.location.hash.substr(1) }) }) }, render() { let Child switch (this.state.route) { case '/about': Child = About; break; case '/inbox': Child = Inbox; break; default: Child = Home; } return ( <div> <h1>App</h1> <ul> <li><a href="#/about">About</a></li> <li><a href="#/inbox">Inbox</a></li> </ul> <Child/> </div> ) } }) render(<App />, document.body)
当hash
值变化的时候,App
将会根据this.state.route
的值决定渲染哪一个组件(About
、Index
、Home
)到页面上。这样的作法虽然看起来很简单,可是也增长了复杂性。服务器
想象一下,若是组件 Inbox
有一些嵌套的子组件,它们的路由规则多是这样的:/inbox/message/12345
或者 /inbox/unread
这样的,
上面的路由匹配规则很显然就不能知足咱们的需求了,咱们不得不修改以前的URL解析规则,写一堆复杂的代码来判断哪一种URL应该呈现哪一个组件(好比:App -> About, App -> Inbox -> Messages -> Message, App -> Inbox -> Messages -> Stats
)。react-router
React Router
首先,引入React Router
dom
import React from 'react' import { render } from 'react-dom' import { Router, Route, Link } from 'react-router'
把判断路由逻辑的那段代码删除,而后加入Link
标签fetch
const App = React.createClass({ render() { return ( <div> <h1>App</h1> {/* 把`a`标签换成`Link`标签 */} <ul> <li><Link to="/about">About</Link></li> <li><Link to="/inbox">Inbox</Link></li> </ul> {/* 把`<Child>`替换成`this.props.children` 路由会渲染正确的组件 */} {this.props.children} </div> ) } })
最后引入<Router>
和<Route>
,由它们帮咱们搞定路由。this
render(( <Router> <Route path="/" component={App}> <Route path="about" component={About} /> <Route path="inbox" component={Inbox} /> </Route> </Router> ), document.body)
React Router
知道哪一种URL
规则下,渲染哪一个组件到页面上,不须要咱们本身在作任何的判断。
例如:/about
这种URL规则,会被构建成<App><About /></App>
在React Router
内部,会把<Route>
标签层级转换成路由配置。若是你不喜欢jsx
的这种写法,也可使用对象的形式:设计
const routes = { path: '/', component: App, childRoutes: [ { path: 'about', component: About }, { path: 'inbox', component: Inbox }, ] } render(<Router routes={routes} />, document.body)
OK,如今在inbox
路由下嵌套一个messages
子路由,
首先须要添加一个新的Message组件:code
const Message = React.createClass({ render() { return <h3>Message</h3> } })
而后在原有的inbox
路由下面为 Message
组件添加新的路由,这样就能够获得嵌套的组件。
const Inbox = React.createClass({ render() { return ( <div> <h2>Inbox</h2> {/* 渲染子组件 */} {this.props.children} </div> ) } }) render(( <Router> <Route path="/" component={App}> <Route path="about" component={About} /> <Route path="inbox" component={Inbox}> {/* 在这里加入要嵌套的视图 */} {/* render the stats page when at `/inbox` */} <IndexRoute component={InboxStats}/> {/* 渲染message组件 /inbox/messages/123 */} <Route path="messages/:id" component={Message} /> </Route> </Route> </Router> ), document.body)
访问inbox/messages/12345
会匹配新加的路由,App->Inbox->Message
,路由层级:
<App> <Inbox> <Message params={ {id: '12345'} } /> </Inbox> </App>
访问/inbox
,路由层级:
<App> <Inbox> <InboxStats /> </Inbox> </App>
当咱们访问inbox/messages/12345
的时候,咱们须要获取到相应的参数,而后从服务器获取对应的数据。当视图渲染的时候,路由组件会注入一些有用的属性到组件上,特别是一些从URL动态获取的参数信息,在咱们这个示例里是:id
const Message = React.createClass({ componentDidMount() { // from the path `/inbox/messages/:id` const id = this.props.params.id fetchMessage(id, function (err, message) { this.setState({ message: message }) }) }, // ... })
你也能够经过查询串来获取参数,假如咱们在浏览器里面访问/foo?bar=baz
这个路由,在你的组件中能够经过this.props.location.query.bar
获取bar
的值baz
。
React Router
基本用法大概就这么多,一个应用每每是各类组件各类嵌套,搞明白了React Router
,就能够很轻松的玩转路由。