React-Router (1)
首先对于 react 来说,即便是没有使用 react-route 也是可以完成需求的,使用 react 提供的 this.state.route
可以渲染不同的页面,虽然使用起来简单,但是面对稍微复杂点儿的应用就会变得有心无力(例如嵌套,列表等结构)。
这个时候,需要使用 React-route 重构应用。
import React from 'react'
import { render } from 'react-dom'
//(1):引入 react-route
import { Router Route Link } from 'react-route'
const App = React.createClass({
render (){
return (
<div>
<ul>
{/* 需要把之前的 a 标签替换为 Link 标签 */}
<li><Link to='/about'>About</li>
<li><Link to='/inbox'>Inbox</li>
</ul>
{/* 之前用的是一个 Child 的小组件,现在替换为{this.props.children} */}
</div>
)
}
})
重要的部分来了,我们用一些 <Route>
来渲染 <Router>
创建一个 <Route>
,这里面是一个一般的嵌套路由
React.render((
<Router>
<Route path="/" component={App}>
<Route path="about" component={About}>
<Route path="inbox" component={Inbox}>
</Route>
</Router>
), document.body);
实际上,route 通过内部处理,将一个完整的路径 /about
自动搭建成 <App><About /></App>
,将你写的树级嵌套结构转变成真正的路由配置,同时也可以用对象(如果不用 JSX 的语法)的方式替代:
const routes = {
path: '/',
component: App,
childRoutes: [
{ path: 'about', component: About },
{ path: 'inbox', component: Inbox },
]
}
渲染组件的时候,react-route 会自动注入一些东西,偶其实动态部分的东西,比如::id
路径中的信息可以通过 this.props.params.id
去获取它,也可以通过访问 this.props.location.query.bar
来获取 /foo?bar=baz
这样URL的 "baz"
值
(2)React-Route 基础路由配置
路由配置的本质是 一组告诉 route 如何匹配 URL,并且如何执行的的指令。
React.render((
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
<Route path="messages/:id" component={Message} />
</Route>
</Route>
</Router>
), document.body)
这段代码是一个标准的不得了的 react-route 代码(官方示例代码,可不TM标准吗)。
URL | 组件 |
---|---|
/ |
App |
/about |
App / about |
/inbox |
App / inbox |
/inbox/messages:id |
App / inbox / messages |
(1)嵌套路由
URL | 组件 |
---|---|
/ |
App |
/about |
App / about |
/inbox |
App / inbox |
/inbox/messages:id |
App / inbox / messages |
(2)解决父路由的默认页面问题
这个时候有一个问题,当 URl 为 /
的时候,我们无法找到这个页面,因为即使加载了App的这个组件,由于是嵌套路由的非最底层,那么 this.props.children
是 undefined,IndexRoute 这个东西可以帮我们默认一个页面,所以上面那个表格有了新的变化。
在标准代码中 path="/"
的路由标签里面加上 <IndexRoute component={Dashboard} />
URL | 组件 |
---|---|
/ |
App / Dashboard |
/about |
App / about |
/inbox |
App / inbox |
/inbox/messages:id |
App / inbox / messages |
URL | 组件 |
---|---|
/ |
App / Dashboard |
/about |
App / about |
/inbox |
App / inbox |
/messages:id |
App / inbox/ messages |
(3)解决URl解耦
这个是一个非常容易遇到的问题,我们的 route 如果嵌套的足够多,会使URL变得异常复杂,那么一个简洁的 URL 是必不可少的,我们可以用 绝对路径。
将标准代码里面的 <Route path="messages/:id" component={Message} />
path 内容改成 /messages/:id
,虽然是多了一个 "/"
,但是我们的 URL 就变成了这个样子
URL | 组件 |
---|---|
/ |
App / Dashboard |
/about |
App / about |
/inbox |
App / inbox |
/messages:id |
App / inbox/ messages |
(4)我们改变了这个 URL ,但访问原来的 URL 会弹出错误页面
我们可以用 <Redirect from = "messages:id" to = "/messages:id">
将之加一个重定向的路由,就不论怎么访问,只要符合要求的就直接跳转过来
(5)题外话,Hook
Hook 是在路由跳转的过程中,两个状态。
整体的改变后的代码是如下:
React.render((
<Router>
<Route path="/" component={App}>
<IndexRoute component={Dashboard} />
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
<Route path="/messages/:id" component={Message} />
{/* 跳转 /inbox/messages/:id 到 /messages/:id */}
<Redirect from="messages/:id" to="/messages/:id" />
</Route>
</Route>
</Router>
), document.body)
需要引入
import { Redirect } from 'react-router'
在嵌套路由中,还有一个优先级的概念:
由于路由算法是从上至下,所以兄弟节点路由配置时,前一个路由节点不能匹配到后一个路由节点。