<Route path='/roster'/>
// when the pathname is '/', the path does not match
// when the pathname is '/roster' or '/roster/2', the path matches
// If you only want to match '/roster', then you need to use
// the "exact" prop. The following will match '/roster', but not
// '/roster/2'.
<Route exact path='/roster'/>
// You might find yourself adding the exact prop to most routes.
// In the future (i.e. v5), the exac t prop will likely be true by
// default. For more information on that, you can check out this
// GitHub issue:
// https://github.com/ReactTraining/react-router/issues/4958
{ number: '6' } // note that the captured value is a string
<Player>组件使用 props.match.params 对象来决定应该渲染哪个球员的资料。
// an API that returns a player object
import PlayerAPI from './PlayerAPI'
const Player = (props) => {
const player = PlayerAPI.get(
parseInt(props.match.params.number, 10)
)
if (!player) {
return <div>Sorry, but the player was not found</div>
}
return (
<div>
<h1>{player.name} (#{player.number})</h1>
<h2>{player.position}</h2>
</div>
)
原文地址:A Simple React Router v4 Tutorial
React Router v4 是一个完全使用 React 重写的流行的 React 包,之前版本的 React Router 版本配置是使用伪组件也很晦涩难懂。现在 v4 版本的 React Router,所有的东西都 “仅仅是组件”。
在这个教程中,我们将建立一个本地的 "运动队" 页面,我们将完成所有的基本需求来建立我们的网站和路由,这包括:
router
。routes
。代码
安装
React Router 现在已经被划分成了三个包:
react-router
,react-router-dom
,react-router-native
。你不应该直接安装
react-router
,这个包为 React Router 应用提供了核心的路由组件和函数,另外两个包提供了特定环境的组件(浏览器和react-native
对应的平台),不过他们也是将react-router
导出的模块再次导出。你应该选择这两个中适应你开发环境的包,我们需要构建一个网站(在浏览器中运行),所以我们要安装
react-router-dom
Router
当开始一个新项目时,你应该决定要使用哪种
router
。对于在浏览器中运行的项目,我们可以选择<BrowserRouter
和<HashRouter>
组件,<BrowserRouter>
应该用在服务器处理动态请求的项目中(知道如何处理任意的URI),<HashRouter>
用来处理静态页面(只能响应请求已知文件的请求)。通常来说更推荐使用
<BrowserRouter>
,可是如果服务器只处理静态页面的请求,那么使用<HashRouter>
也是一个足够的解决方案。对于我们的项目,我们假设所有的页面都是由服务器动态生成的,所以我们的
router
组件选择<BrowserRouter>
。History
每个
router
都会创建一个history
对象,用来保持对当前位置[1]的追踪还有在页面发生变化的时候重新渲染页面。React Router 提供的其他组件依赖在context
上储存的history
对象,所以他们必须在router
对象的内部渲染。一个没有router
祖先元素的 React Router 对象将无法正常工作,如果你想学习更多的关于history
对象的知识,可以参照 这篇文章。渲染一个
<Router>
Router 的组件只能接受一个子元素,为了遵照这种限制,创建一个
<App>
组件来渲染其他的应用将非常方便(将应用从 router 中分离对服务器端渲染也有重要意义,因为我们在服务器端转换到<MemoryRouter>
时可以很快复用<App>
)现在我们已经选择了 router,我们可以开始渲染我们真正的应用了。
<App>
我们的应用定义在
<App>
组件中,为了简化<App>
,我们将我们的应用分为两个部分,<Header>
组件包含链接到其他页面的导航,<Main>
组件包含其余的需要渲染的部分。Note: 你可以任意布局你的应用,分离 routes 和导航让你更加容易了解 React Router 是如何工作的。
我们先从渲染我们路由内容的
<Main>
组件开始。Routes
<Route>
组件是 React Router 的主要组成部分,如果你想要在路径符合的时候在任何地方渲染什么东西,你就应该创造一个<Route>
元素。Path
一个
<Route>
组件需要一个 string 类型的path
prop 来指定路由需要匹配的路径。举例来说,<Route path='/roster/'
将匹配以/roster
[2] 开始的路径,当当前的路径和path
匹配时,route 将会渲染对应的 React 元素。当路径不匹配的时候 ,路由不会渲染任何元素 [3]。Note: 在匹配路由的时候,React Router 只会关心相对路径的部分,所以如下的 URL
React Router 只会尝试匹配
/my-projects/one
。匹配路径
React Router使用
path-to-regexp
包来判断路径的path
prop 是否匹配当前路径,它将path
字符串转换成正则表达式与当前的路径进行匹配,关于path
字符串更多的可选格式,可以查阅path-to-regexp
文档。当路由与路径匹配的时候,一个具有以下属性的
match
对象将会被作为 prop 传入url
- 当前路径与路由相匹配的部分path
- 路由的path
isExact
-path === pathname
params
- 一个包含着pathname
被path-to-regexp
捕获的对象Note: 目前,路由的路径必须是绝对路径 [4]。
创建我们自己的路由
<Route>
s 可以在router中的任意位置被创建,不过一般来说将他们放到同一个地方渲染更加合理,你可以使用<Switch>
组件来组合<Route>
s,<Switch>
将遍历它的children
元素(路由),然后只匹配第一个符合的pathname
。对于我们的网站来说,我们想要匹配的路径为:
/
- 主页/roster
- 队伍名单/roster/:number
- 队员的资料,使用球员的球衣号码来区分/schedule
- 队伍的赛程表为了匹配路径,我们需要创建带
path
prop的<Route>
元素<Route>
将会渲染什么Routes 可以接受三种 prop 来决定路径匹配时渲染的元素,只能给
<Route>
元素提供一种来定义要渲染的内容。<component>
- 一个 React 组件,当一个带有component
prop 的路由匹配的时候,路由将会返回 prop 提供的 component 类型的组件(通过React.createElement
渲染)。render
- 一个返回 React 元素 [5] 的方法,与component
类似,也是当路径匹配的时候会被调用。写成内联形式渲染和传递参数的时候非常方便。children
- 一个返回 React 元素的方法。与前两种不同的是,这种方法总是会被渲染,无论路由与当前的路径是否匹配。一般来说,我们一般使用
component
或者render
,children
的使用场景不多,而且一般来说当路由不匹配的时候最好不要渲染任何东西。在我们的例子中,不需要向路由传递任何参数,所有我们使用<component>
。由
<Route>
渲染的元素将会带有一系列的 props,有match
对象,当前的location
对象 [6],还有history
对象(由 router 创建)[7]。<Main>
现在我们已经确定了 route 的结构,我们只需要将他们实现即可。在我们的应用中,我们将会在
<Main>
组件中渲染<Switch>
和<Route>
,它们将会在<main>
中渲染 HTML 元素。Note: 主页的路由带有
exact
prop,这表明只有路由的 path 完全匹配 pathname 的时候才会匹配主页。路由的嵌套
队员资料页的路由
/roster/:number
是在<Roster>
组件而没有包含在<Switch>
中。但是,只要 pathname 由/roster
开头,它就会被<Roster>
组件渲染。在
<Roster>
组件中我们将渲染两种路径:/roster
- 只有当路径完全匹配/roster
时会被渲染,我们要对该路径指定exact
参数。/roster/:number
- 这个路由使用一个路径参数来捕获/roster
后面带的 pathname 的部分。将带有相同前缀的路由放在同一个组件中很方便,这样可以简化父组件并且让我们可以让我们在一个地方渲染所有带有相同前缀的组件。
举个例子,
<Roster>
可以为所有以/roster
开头的路由渲染一个标题Path 参数
有的时候我们想捕捉 pathname 中的多个参数,举例来说,在我们的球员资料路由中,我们可以通过向路由的
path
添加路径参数来捕获球员的号码。:number
部分代表在pathname中/roster/
后面的内容将会被储存在match.params.number
。举例来说,一个为/roster/6
的 pathname 将会生成一个如下的params 对象。<Player>
组件使用props.match.params
对象来决定应该渲染哪个球员的资料。关于
path
参数可以查阅path-to-regexp
文档。紧挨着
<Player>
,还有一个<FullRoster>
,<Schedule>
和<Home>
组件。Links
最后,我们的网站需要在页面之间导航,如果我们使用
<a>
标签导航的话,将会载入一整个新的页面。React Router 提供了一个<Link>
组件来避免这种情况,当点击<Link>
时,URL 将会更新,页面也会在不载入整个新页面的情况下渲染内容。<Link>
s 使用to
prop 来决定导航的目标,可以是一个字符串,或者是一个 location 对象(包含pathname
,search
,hash
和state
属性)。当只是一个字符串的时候,将会被转化为一个 location 对象Note: 目前,链接的 pathname 必须是绝对路径。
例子
两个在线的例子:
Notes!
[1] locations 是包含描述 URL 不同部分的参数的对象
[2] 可以一个无路径的
<Route>
,这个路由将会匹配所有路径,这样可以很方便的访问存储在context
上的对象和方法。[3] 当使用
children
prop 时,即使在路径不匹配的时候也会渲染。[4] 让
<Route>
s 和<Link>
s 接受相对路径的工作还未完成,相对的<Link>
s 比看上去要复杂的多,因为它们需要父组件的match
对象来工作,而不是当前的 URL。[5] 这是个基本的无状态组件,
component
和render
的区别是,component
会使用React.createElement
来创建一个元素,render
使用将组件视作一个函数。如果你想创建一个内联函数并传递给component
,那么render
会比component
来的快得多。[6]
<Route>
和<Switch>
组件都可以接受一个location
prop,这可以让他们被一个不同的 location 匹配到,而不仅仅是他们实际的 location(当前的 URL)。[7] props 也可以传递
staticContext
这个 prop,但是只在使用服务端渲染的时候有效。