children 的值也是一个函数,函数返回要渲染的 React 元素。 与前两种方式不同之处是,无论是否匹配成功, children 返回的组件都会被渲染。但是,当匹配不成功时,match 属性为 null。例如:
<Route path='/foo' render={(props) => { <div className={props.match ? 'active': ''}> <Foo {...props} data={extraProps} /> </div> }}> </Route>
如果 Route 匹配当前 URL,待渲染元素的根节点 div 的 class 将设置成 active.
4)Switch 和 exact
当URL 和多个 Route 匹配时,这些 Route 都会执行渲染操作。如果只想让第一个匹配的 Route 沉浸,那么可以把这些 Route 包到一个 Switch 组件中。如果想让 URL 和 Route 完全匹配时,Route才渲染,那么可以使用 Route 的 exact 属性。Switch 和 exact 常常联合使用,用于应用首页的导航。例如:
<Router> <Switch> <Route exact path='https://www.jb51.net/' component={Home}/> <Route exact path='/posts' component={Posts} /> <Route exact path='/:user' component={User} /> </Switch> </Router>
如果不使用 Switch,当 URL 的 pathname 为 "/posts" 时,<Route path='/posts' /> 和 <Route path=':user' /> 都会被匹配,但显然我们并不希望 <Route path=':user' /> 被匹配,实际上也没有用户名为 posts 的用户。如果不使用 exact, "https://www.jb51.net/" "/posts" "/user1"等几乎所有 URL 都会匹配第一个 Route,又因为Switch 的存在,后面的两个 Route永远不会被匹配。使用 exact,保证 只有当 URL 的 pathname 为 'https://www.jb51.net/'时,第一个Route才会匹配。
5)嵌套路由
嵌套路由是指在Route 渲染的组件内部定义新的 Route。例如,在上一个例子中,在 Posts 组件内再定义两个 Route:
const Posts = ({match}) => { return ( <div> {/* 这里 match.url 等于 /posts */} <Route path={`${match.url}/:id`} component={PostDetail} /> <Route exact path={match.url} component={PostList} /> </div> ) }
五、链接
Link 是 React Router提供的链接组件,一个 Link 组件定义了当点击该 Link 时,页面应该如何路由。例如:
const Navigation = () => { <header> <nav> <ul> <li><Link to='https://www.jb51.net/'>Home</Link></li> <li><Link to='/posts'>Posts</Link></li> </ul> </nav> </header> }
Link 使用 to 属性声明要导航到的URL地址。to 可以是 string 或 object 类型,当 to 为 object 类型时,可以包含 pathname、search、hash、state 四个属性,例如:
<Link to={{ pathname: '/posts', search: '?sort=name', hash:'#the-hash', state: { fromHome: true} }}> </Link>
除了使用Link外,我们还可以使用 history 对象手动实现导航。history 中最常用的两个方法是 push(path,[state]) 和 replace(path,[state]),push会向浏览器记录中新增一条记录,replace 会用新记录替换记录。例如:
history.push('/posts'); history.replace('/posts');
六、路由设计
路由设计的过程可以分为两步:
为每一个页面定义有语义的路由名称(path)
组织 Route 结构层次
1)定义路由名称
我们有三个页面,按照页面功能不难定义出如下的路由名称:
登录页: /login
帖子列表页: /posts
帖子详情页: /posts/:id(id代表帖子的ID)
但是这些还不够,还需要考虑打开应用时的默认页面,也就是根路径"https://www.jb51.net/"对应的页面。结合业务场景,帖子列表作为应用的默认页面为合适,因此,帖子列表对应两个路由名称: '/posts'和 'https://www.jb51.net/'
2)组织 Route 结构层次