react-router 4.x 使用教程

react-router 4.x 简单教程说明

具体完整的代码

React Router4 是一个流行的纯 React 重写的包。现在的版本中已不需要路由配置,现在一切皆组件

安装


React Router 被拆分成三个包:react-router,react-router-domreact-router-nativereact-router提供核心的路由组件与函数。其余两个则提供运行环境(即浏览器与 react-native)所需的特定组件。
进行网站构建,我们应当安装react-router-dom,react-router-dom暴露出react-router中暴露的对象与方法,因此你只需要安装并引用react-router-dom即可。

1
yarn add react-router-dom

路由器(Router)


在你开始项目前,你需要确定你使用的路由的类型,对于网页项目,存在<BrowersRouter><HashRouter>两种组件
当存在服务取来管理动态请求时,需要使用<BrowserRouter>组件,而<HashRouter>被用于静态网站。
通常我们更倾向于<BrowserRouter>,但如果你的网站仅用来呈现静态文件,那么<HashRouter>将会是一个更好的选择

历史(History)


每个路由器都会创建一个 history 对象并用其保持追踪当前 location 并且在有变化时对网站进行重新渲染。这个 history 对象保证了 React Router 提供的其他组件的可用性,所以其他组件必须在 router 内部渲染。一个 React Router 组件如果向父级上追溯却找不到 router 组件,那么这个组件将无法正常工作。

渲染<Router>


路由器组件无法接受两个及以上的子元素。基于这种限制的存在,创建一个<App>组件来渲染应用其余部分是一个有效的方法(对于服务端渲染,将应用从 router 组件中分离也是重要的)。

1
2
3
4
5
6
7
8
9
10
<!-- index.js -->
import { BrowserRouter } from 'react-router-dom'

ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>),
document.getElementById('root'));
registerServiceWorker();

App.js


应用通过<App>组件定义。简化一下,我们将应用拆分成两个部分。<Nav>组件包含网站的导航链接。<Main>组件则呈现其余内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- App.js -->
import { Switch, Route,Link } from 'react-router-dom'

const App = () => (
<div>
<header>
<nav>
<ul>
<li><Link to='/'>Home</Link></li>
<li><Link to='/roster'>Roster</Link></li>
<li><Link to='/schedule'>Schedule</Link></li>
</ul>
</nav>
</header>
<Switch>
<Route exact path='/' component={Home}/>
<Route path='/roster' component={Roster}/>
<Route path='/schedule' component={Schedule}/>
</Switch>
</div>
)

路径(Path)


<Route>接受一个数为 string 类型的 path,该值路由匹配的路径名的类型。例如:<Route path='/roster'/>会匹配以/roster 开头的路径名。在当前 path 参数与当前 location 的路径相匹配时,路由就会开始渲染 React 元素。若不匹配,路由不会进行任何操作。

1
2
3
4
5
6
<Route path='/roster'/>
// 当路径名为'/'时, path不匹配
// 当路径名为'/roster'或'/roster/2'时, path匹配
// 当你只想匹配'/roster'时,你需要使用"exact"参数
// 则路由仅匹配'/roster'而不会匹配'/roster/2'
<Route exact path='/roster'/>

创建你的路由


可以在路由器(router)组件中的任意位置创建多个<Route>,但通常我们会把它们放在同一个位置。使用<Switch>组件来包裹一组<Route><Switch>会遍历自身的子元素(即路由)并对第一个匹配当前路径的元素进行渲染。
为了在应用中能匹配路径,在创建<Route>元素时必须带有需要匹配的 path 作为参数

1
2
3
4
5
6
7
import { Switch, Route } from "react-router-dom";
<Switch>
<Route exact path="/" component={Home} />
{/* both /roster and /roster/:number begin with /roster */}
<Route path="/roster" component={Roster} />
<Route path="/schedule" component={Schedule} />
</Switch>;

路径参数


有时路径名中存在我们需要获取的参数。例如,在运动员界面,我们需要获取运动员的编号。我们可以向 route 的路径字符串中添加 path 参数

如’/roster/:number’中:number这种写法意味着/roster/后的路径名将会被获取并存在match.params.number中。例如,路径名’/roster/6’会获取到一个对象:

1
2
3
{
number: "6";
} // 注获取的值是字符串类型的

组件可以使用props.match.params对象来确定需要被渲染的运动员的数据。

1
...parseInt(props.match.params.number, 10)

现在,我们应用需要在各个页面间切换。如果使用锚点元素(就是)实现,在每次点击时页面将被重新加载。React Router 提供了<Link>组件用来避免这种状况的发生。当你点击<Link>时,URL 会更新,组件会被重新渲染,但是页面不会重新加载。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { Link } from 'react-router-dom'
const Header = () => (
<header>
<nav>
<ul>
<li><Link to='/'>Home</Link></li>
<li><Link to='/roster'>About</Link></li>
<li><Link to='/schedule'>Me</Link></li>
</ul>
</nav>
</header>
)
<Link>使用'to'参数来描述需要定位的页面。它的值即可是字符串也可是location对象(包含pathname,search,hash与state属性)。如果其值为字符床将会被转换为location对象。

<Link to={{ pathname: '/roster/7' }}>Player #7</Link>