<Route>
想要理解并使用好React Router,最重要的可能就是Route组件了。Route组件主要的作用就是当一个location匹配路由的path
时,渲染某些UI。
考虑这样的代码:
import { BrowserRouter as Router, Route } from 'react-router-dom'
<Router>
<div>
<Route exact path="/" component={Home}/>
<Route path="/news" component={NewsFeed}/>
</div>
</Router>
如果应用的地址是/
,那么相应的UI会类似这个样子:
<div>
<Home/>
<!-- react-empty: 2 -->
</div>
如果应用的地址是/news
,那么相应的UI就会成为这个样子:
<div>
<!-- react-empty: 1 -->
<NewsFeed/>
</div>
这里的react-empty
注释只是演示了React渲染null
的细节,但对我们具有启发性。其实Route就算是null
也会被渲染,只要地址与路由的路径匹配,组件就会渲染。
Route渲染方法
使用<Route>
有三种渲染内容的方法:
在不同的情况下每个都特别有用,对于某个<Route>
,你只能使用这些props
其中的一个,绝大多数的时候会使用component
。
Route props
这三种渲染方法都会获得相同的三个的属性:
component
只有在地址匹配的时候React的组件才会被渲染,route props也会随着一起被渲染。
<Route path="/user/:username" component={User}/>
const User = ({ match }) => {
return <h1>Hello {match.params.username}!</h1>
}
如果你使用component
(而不是像下面这样使用render
),路由会根据指定的组件使用React.createElement
来创建一个新的React element。这就意味着如果你提供的是一个内联的函数的话会带来很多意料之外的重新挂载。所以,对于内联渲染,要使用render
属性(如下所示)。
render: func
这种方式对于内联渲染和包装组件却不引起意料之外的重新挂载特别方便。
使用render
属性,你可以选择传一个在地址匹配时被调用的函数,而不是像使用component
属性那样得到一个新创建的React element。使用render
属性会获得跟使用component
属性一样的route props。
// 便捷的行内渲染
<Route path="/home" render={() => <div>Home</div>}/>
// 包装/合成
const FadingRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
<FadeIn>
<Component {...props}/>
</FadeIn>
)}/>
)
<FadingRoute path="/cool" component={Something}/>
警告: <Route component>
的优先级要比<Route render>
高,所以不要在同一个 <Route>
中同时使用这两个属性。
children: func
有时候你可能想不管地址是否匹配都渲染一些内容,这种情况你可以使用children
属性。它与render
属性的工作方式基本一样,除了它是不管地址匹配与否都会被调用。
除了在路径不匹配URL时match
的值为null
之外,children
渲染属性会获得与component
和render
一样的route props。这就允许你根据是否匹配路由来动态地调整UI了,来看这个例子,如果理由匹配的话就添加一个active
类:
<ul>
<ListItemLink to="/somewhere"/>
<ListItemLink to="/somewhere-else"/>
</ul>
const ListItemLink = ({ to, ...rest }) => (
<Route path={to} children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest}/>
</li>
)}/>
)
这种属性对于动画也特别有用:
<Route children={({ match, ...rest }) => (
{/* Animate总会被渲染, 所以你可以使用生命周期来使它的子组件出现
或者隐藏
*/}
<Animate>
{match && <Something {...rest}/>}
</Animate>
)}/>
Warning: <Route component>
和<Route render>
的优先级都比<Route children>
高,所以在同一个<Route>
中不要同时使用一个以上的属性.
path: string
可以是任何path-to-regexp
能理解的有效URL。
<Route path="/users/:id" component={User}/>
没有path
属性的Route 总是会 匹配。
exact: bool
当值为true
时,则要求路径与location.pathname
必须 完全 匹配。
<Route exact path="/one" component={About}/>
路径 | location.pathname | exact | 是否匹配? |
---|---|---|---|
/one |
/one/two |
true |
否 |
/one |
/one/two |
false |
是 |
strict: bool
当设为true
的时候,有结尾斜线的路径只能匹配有斜线的location.pathname
,这个值并不会对location.pathname
中有其他的片段有影响。
<Route strict path="/one/" component={About}/>
路径 | location.pathname | 是否匹配? |
---|---|---|
/one/ |
/one |
否 |
/one/ |
/one/ |
是 |
/one/ |
/one/two |
是 |
警告: stict
可以强制location.pathname
不包含结尾的斜线,但是要做到这点必须把strict
和exect
都设置为true
。
<Route exact strict path="/one" component={About}/>
路径 | location.pathname | 是否匹配? |
---|---|---|
/one |
/one |
是 |
/one |
/one/ |
否 |
/one |
/one/two |
否 |