这篇文章是整理自己学习react-router的一些简单用法和学习资料整理,用作自己的备忘录同时分享。
入门学习
基础用法
将官方示例克隆下来,运行命令执行起来。
首先添加一个路由:打开入口js文件index.js
:
// render(<App/>, document.getElementById('app'))
render(<Router/>, document.getElementById('app'))
Router
是一个组件,也就是react-router
,改写代码:
render(
<Router history={hashHistory}>
<Route path="/" component={App}/>
</Router>
,document.getElementById('app'))
现在我们看到和启动前一样的页面,我们可以试着多加几个路由。
新添加两个组件
modules/About.js
modules/Repos.js
// modules/About.js
import React from 'react'
export default React.createClass({
render() {
return <div>About</div>
}
})
新添加两个路由
render(
<Router history={hashHistory}>
<Route path="/" component={App}/>
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Router>
,document.getElementById('app'))
Route
组件定义了URL路径与组件的对应关系。
上面代码中,用户访问/repos(比如http://localhost:8080/#/repos)时,加载Repos组件;访问/about(http://localhost:8080/#/about)时,加载About组件。
Link
Link组件用于取代<a>元素,生成一个链接,允许用户点击后跳转到另一个路由。
编辑modules/App.js
:
import { Link } from 'react-router'
export default React.createClass({
render() {
return <div>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
</div>
}
})
嵌套路由
之前在app上我们添加了两个链接,相当于导航的功能,但是导航应该在每个页面都应该有。我们的应用就像盒子,一个装一个,我们的链接也是一层一层往下的,假如给定url:/repos/123
,我们的组件可能就像这样:
<App> {/* / */}
<Repos> {/* /repos */}
<Repo/> {/* /repos/123 */}
</Repos>
</App>
react的链接和我们的组件(UI)是一致的,链接和UI组件的加载是一个层级关系,3级链接就会依次加载三个路由的组件。
下面我们来实现公共导航:
首先我们书写嵌套路由:
render(
<Router history={hashHistory}>
<Route path="/" component={App}>
{/* make them children of `App` */}
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Route>
</Router>
,document.getElementById('app'))
组件的嵌套关系,就像父子关系,有孩子就有父,嵌套内的路由是外面一层的children
,我们需要把这个子组件放在父组件对应的位置:
// modules/App.js
// ...
render() {
return (
<div>
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
{/* add this */}
{this.props.children}
</div>
)
}
// ...
现在看页面,就是链接切换时一直在顶部。只是替换了不同的子组件,像这样:
// at /about
<App>
<About/>
</App>
// at /repos
<App>
<Repos/>
</App>
有了导航,我想给对应导航添加当前的样式呢,react-router提供了activeStyle
和activeClassName
,直接添加内联样式和添加类名来定义链接当前样式。
每次写当前样式都需要加一个active,有点麻烦,也不一定我们都记得,我们可以在Link上在封装一层,作为导航链接。
// modules/NavLink.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return <Link {...this.props} activeClassName="active"/>
}
})
现在我们就可以这样使用:
// modules/App.js
import NavLink from './NavLink'
// ...
<li><NavLink to="/about">About</NavLink></li>
<li><NavLink to="/repos">Repos</NavLink></li>
路由参数
路由路劲:paramName
后的url会被作为参数,值可以在组件中解析this.props.params[name]
,我们试试在示例中添加参数来理解一下:
render(
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
<Route path="/repo/:userName/:repoName" component={Repo}/>
</Route>
</Router>
,document.getElementById('app'))
然后新建一个组件:
import React from 'react'
export default React.createClass({
render() {
return (
<div>
<p>第一个链接参数{this.props.params.userName}</p>
<p>第二个链接参数{this.props.params.repoName}</p>
</div>
)
}
})
然后在链接上加一个链接试试:
<li><NavLink to="/repo/zhang/123">带参数的链接</NavLink></li>
路由中的参数名称会成为对应组件的属性名称。
IndexRoute
我们可以通过IndexRoute
设置一个默认加载的组件。
比如我们需要给应用添加一个首页,我们添加一个默认加载的组件:
import React from 'react'
export default React.createClass({
render() {
return <div>Home</div>
}
})
然后运用IndexRoute
添加默认加载的组件:
render(
<Router history={hashHistory}>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
<Route path="/repo/:userName/:repoName" component={Repo}/>
</Route>
</Router>
,document.getElementById('app'))
现在在http://localhost:8080/不仅会加载App
组件,也会加载Home
组件。
IndexLink
看看我们的例子,现在我们没有连接可以回到首页,我们试着添加一个连接到首页:
<li><NavLink to="/">Home</NavLink></li>
然而这个Home连接一直在当前状态,也就是一直是红色状态。因为/
是所有根路径,所有的路径都会匹配它,所以他一直是红色状态。react-router提供了IndexLink
来解决这个问题,用这个试试:
<li><IndexLink to="/" activeStyle={{ color: 'red' }}>Home</IndexLink></li>
history
高级用法
动态路由
对于大型应用来说,一个首当其冲的问题就是所需加载的 JavaScript 的大小。程序应当只加载当前渲染页所需的 JavaScript以及组件。
Route
可以定义getChildRoute
、getIndexRoute
、getComponents
这几个函数。他们都是异步执行的,并且只在需要时才被调用。React Router 会逐渐的匹配 URL 并只加载该 URL 对应页面所需的路径配置和组件。
const CourseRoute = {
path: 'course/:courseId',
getChildRoutes(location, callback) {
require.ensure([], function (require) {
callback(null, [
require('./routes/Announcements'),
require('./routes/Assignments'),
require('./routes/Grades'),
])
})
},
getIndexRoute(location, callback) {
require.ensure([], function (require) {
callback(null, require('./components/Index'))
})
},
getComponents(location, callback) {
require.ensure([], function (require) {
callback(null, require('./components/Course'))
})
}
}