<Route>

想要理解并使用好React Router,最重要的可能就是Route组件了。Route组件主要的作用就是当一个location匹配路由的path时,渲染某些UI。

考虑这样的代码:

  1. import { BrowserRouter as Router, Route } from 'react-router-dom'
  2. <Router>
  3. <div>
  4. <Route exact path="/" component={Home}/>
  5. <Route path="/news" component={NewsFeed}/>
  6. </div>
  7. </Router>

如果应用的地址是/,那么相应的UI会类似这个样子:

  1. <div>
  2. <Home/>
  3. <!-- react-empty: 2 -->
  4. </div>

如果应用的地址是/news,那么相应的UI就会成为这个样子:

  1. <div>
  2. <!-- react-empty: 1 -->
  3. <NewsFeed/>
  4. </div>

这里的react-empty注释只是演示了React渲染null的细节,但对我们具有启发性。其实Route就算是null也会被渲染,只要地址与路由的路径匹配,组件就会渲染。

Route渲染方法

使用<Route>有三种渲染内容的方法:

在不同的情况下每个都特别有用,对于某个<Route>,你只能使用这些props其中的一个,绝大多数的时候会使用component

Route props

这三种渲染方法都会获得相同的三个的属性:

component

只有在地址匹配的时候React的组件才会被渲染,route props也会随着一起被渲染。

  1. <Route path="/user/:username" component={User}/>
  2. const User = ({ match }) => {
  3. return <h1>Hello {match.params.username}!</h1>
  4. }

如果你使用component(而不是像下面这样使用render),路由会根据指定的组件使用React.createElement来创建一个新的React element。这就意味着如果你提供的是一个内联的函数的话会带来很多意料之外的重新挂载。所以,对于内联渲染,要使用render属性(如下所示)。

render: func

这种方式对于内联渲染和包装组件却不引起意料之外的重新挂载特别方便。

使用render属性,你可以选择传一个在地址匹配时被调用的函数,而不是像使用component属性那样得到一个新创建的React element。使用render属性会获得跟使用component属性一样的route props

  1. // 便捷的行内渲染
  2. <Route path="/home" render={() => <div>Home</div>}/>
  3. // 包装/合成
  4. const FadingRoute = ({ component: Component, ...rest }) => (
  5. <Route {...rest} render={props => (
  6. <FadeIn>
  7. <Component {...props}/>
  8. </FadeIn>
  9. )}/>
  10. )
  11. <FadingRoute path="/cool" component={Something}/>

警告: <Route component>的优先级要比<Route render>高,所以不要在同一个 <Route>中同时使用这两个属性。

children: func

有时候你可能想不管地址是否匹配都渲染一些内容,这种情况你可以使用children属性。它与render属性的工作方式基本一样,除了它是不管地址匹配与否都会被调用。

除了在路径不匹配URL时match的值为null之外,children渲染属性会获得与componentrender一样的route props。这就允许你根据是否匹配路由来动态地调整UI了,来看这个例子,如果理由匹配的话就添加一个active类:

  1. <ul>
  2. <ListItemLink to="/somewhere"/>
  3. <ListItemLink to="/somewhere-else"/>
  4. </ul>
  5. const ListItemLink = ({ to, ...rest }) => (
  6. <Route path={to} children={({ match }) => (
  7. <li className={match ? 'active' : ''}>
  8. <Link to={to} {...rest}/>
  9. </li>
  10. )}/>
  11. )

这种属性对于动画也特别有用:

  1. <Route children={({ match, ...rest }) => (
  2. {/* Animate总会被渲染, 所以你可以使用生命周期来使它的子组件出现
  3. 或者隐藏
  4. */}
  5. <Animate>
  6. {match && <Something {...rest}/>}
  7. </Animate>
  8. )}/>

Warning: <Route component><Route render> 的优先级都比<Route children> 高,所以在同一个<Route>中不要同时使用一个以上的属性.

path: string

可以是任何path-to-regexp能理解的有效URL。

  1. <Route path="/users/:id" component={User}/>

没有path属性的Route 总是会 匹配。

exact: bool

当值为true时,则要求路径与location.pathname必须 完全 匹配。

  1. <Route exact path="/one" component={About}/>
路径 location.pathname exact 是否匹配?
/one /one/two true
/one /one/two false

strict: bool

当设为true的时候,有结尾斜线的路径只能匹配有斜线的location.pathname,这个值并不会对location.pathname中有其他的片段有影响。

  1. <Route strict path="/one/" component={About}/>
路径 location.pathname 是否匹配?
/one/ /one
/one/ /one/
/one/ /one/two

警告: stict可以强制location.pathname不包含结尾的斜线,但是要做到这点必须把strictexect都设置为true

  1. <Route exact strict path="/one" component={About}/>
路径 location.pathname 是否匹配?
/one /one
/one /one/
/one /one/two