我们给App
添加的导航栏现在已经成功地显示在页面上了。不使用React Router,我们可以把ul
做成一个组件,即Nav
,然后把Nav
渲染到我们的屏幕上。
你注意到你的应用像下图中那样相互嵌套在盒子里面吗?你注意到你的URLs变成像/repos/123
这样了吗?我们组件的结构就如下图所示:
React Router接受这样把路由给结合在一起,称为结合UI。
图片.png分享我们的导航
让我们把About
和Repos
组件给结合起来到App
当中,并将其导航链接给分享至屏幕中去。我们需要做下面的两个步骤:
首先,让App
的路由有子节点,并将其他的路由放到该子节点当中去。
index.js
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
render((
<Router history={hashHistory}>
<Route path="/" component={App}/>
<Route path="/repos" component={Repos}/>
<Route path="/about" component={About}/>
</Router>
), document.getElementById('app'))
接着我们在App
当中渲染该子节点。
moudules/App.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
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>
{this.props.children}
</div>
)
}
})
图片.png
好了,现在点击链接而且注意到App
会持续得渲染子路由组件通过this.props.children
。
有一种方法可以让Link
区别于a
,那就是让链接可以动态地更换自身的风格。
让我们看看如何用内联的方法,添加activeStyle
到你的Link
上。
modules/App.js
<li><Link to="/about" activeStyle={{ color: 'red' }}>About</Link></li>
<li><Link to="/repos" activeStyle={{ color: 'green' }}>Repos</Link></li>
图片.png
现在我们只要用鼠标点击一下,导航栏就会变成红色了的。
图片.png我们同样可以使用Class Name
。
modules/App.js
我们不必将样式写在该页面上去。让我们添加一个额外的link
标签。
index.html
<link rel="stylesheet" href="index.css">
效果如图所示:
图片.png 图片.png网站中的大多数的链接不必知道他们是否是活跃的,通常只有主要的链接是需要知道的而已。将那些你不必去记住的activeClassName
和activeStyle
给包裹起来。
我们将使用一个展开的操作器,也就是三个点。使用这种方法,它会克隆我们的属性activeClassName
到我们想要的组件。
创建一个文件为NavLink.js
在modules文件目录下。
NavLink.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return <Link {...this.props} activeClassName="active"/>
}
})
图片.png
接着我们将链接换成NavLink
。
modules/App.js
import React from 'react'
import { Link } from 'react-router'
import NavLink from './NavLink'
export default React.createClass({
render() {
return (
<div>
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><NavLink to="/about">About</NavLink></li>
<li><NavLink to="/repos">Repos</NavLink></li>
</ul>
</div>
)
}
})
图片.png
现在我们点击这两个链接并不会直接跳转。
图片.pngURL参数
考虑下面的URL,如上图所示。
这些URL会匹配路由的路径,比如:
/repos/:userName/:repoName
参数是从:
开始的:这些URL参数将会被解析以及变为可以访问的路由组件通过this.props.params[name]
。
给路由添加参数
让我们的应用在屏幕上去如何渲染/repos/:userName/:repoName
。
首先我们需要一个组件去渲染这个路由,新建一个文件夹modules/Repo.js:
代码如下:
Repo.js
import React from 'react'
export default React.createClass({
render() {
return (
<div>
<h2>{this.props.params.repoName}</h2>
</div>
)
}
})
index.js
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App'
import About from './modules/About'
import Repos from './modules/Repos'
import Repo from './modules/Repo'
render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/repos" component={Repos}/>
<Route path="/repos/:userName/:repoName" component={Repo}/>
<Route path="/about" component={About}/>
</Route>
</Router>
), document.getElementById('app'))
Repos.js
import React from 'react'
import { Link } from 'react-router'
export default React.createClass({
render() {
return (
<div>
<h2>Repos</h2>
<ul>
<li><Link to="/repos/reactjs/react-router">React Router</Link></li>
<li><Link to="/repos/facebook/react">React</Link></li>
</ul>
</div>
)
}
})
图片.png
现在路由路径的参数名称已经变成组件的属性了。repoName
和userName
已经可以组件中通过this.props.params
来访问到。
注意,当我们导航到不同的仓库时,其他的导航链接是如何消失的?
首先,将Repo
路由给聚集到Repos
路由下。然后在Repos
用this.props.children
渲染。
动态链接
让我们把active
属性添加到NavLink
上。
modules/Repos.js
import React from 'react'
import { Link } from 'react-router'
import NavLink from './NavLink'
export default React.createClass({
render() {
return (
<div>
<h2>Repos</h2>
<ul>
<li><NavLink to="/repos/reactjs/react-router">React Router</NavLink></li>
<li><NavLink to="/repos/facebook/react">React</NavLink></li>
</ul>
{this.props.children}
</div>
)
}
})
图片.png
图片.png
索引路由
当我们通过/
访问一个空白的界面,我们想要渲染一个Home
组件在这个空白的界面。我们创建这个组件并试着如何去渲染它。
代码太多我就偷懒不贴上来了,看图就好:
图片.png 图片.png 图片.png打开localhost:8080
,显示如下:
IndexRoute我看得不是很懂,所以下面的内容我是搬运阮一峰老师的:
下面的例子,你会不会觉得有一点问题?
<Router>
<Route path="/" component={App}>
<Route path="accounts" component={Accounts}/>
<Route path="statements" component={Statements}/>
</Route>
</Router>
上面代码中,访问根路径/
,不会加载任何子组件。也就是说,App
组件的this.props.children
,这时是undefined
。
因此,通常会采用{this.props.children || <Home/>}
这样的写法。这时,Home
明明是Accounts
和Statements
的同级组件,却没有写在Route
中。
IndexRoute
就是解决这个问题,显式指定Home
是根路由的子组件,即指定默认情况下加载的子组件。你可以把IndexRoute
想象成某个路径的index.html
。
<Router>
<Route path="/" component={App}>
<IndexRoute component={Home}/>
<Route path="accounts" component={Accounts}/>
<Route path="statements" component={Statements}/>
</Route>
</Router>
现在,用户访问/
的时候,加载的组件结构如下。
<App>
<Home/>
</App>
这种组件结构就很清晰了:App
只包含下级组件的共有元素,本身的展示内容则由Home组件定义。这样有利于代码分离,也有利于使用React Router提供的各种API。
注意,IndexRoute
组件没有路径参数path
。
总结一下,IndexRoute就是默认加载显示的那个组件。
网友评论