logo头像
Snippet 博客主题

React Router

参考链接

React router 中文文档
React Router 中文文档(一)
React-router4简约教程
React-router v4教程
react-router v4 之 啥是

React-router vs react-router-dom vs react-router-native

  • react-router是浏览器和原生应用的通用部分。
  • react-router-dom是用于浏览器的。
  • react-router-native是用于原生应用的。

react-router是核心部分。react-router-dom提供了浏览器使用需要的定制组件。react-router-native则专门提供了在原生移动应用中需要用到的部分。所以,在现代浏览器使用就只需要安装react-router-dom。

安装

1
yarn add react-router-dom

BrowserRouter vs HashRouter

HashRouter

Hash history 使用 URL 中的 hash(#)部分去创建形如 example.com/#/some/path 的路由。

BrowserRouter(推荐使用)

<BrowserRouter> 使用 HTML5 提供的 history API (pushState, replaceState 和 popstate 事件) 来保持 UI 和 URL 的同步。

1
2
3
4
5
6
7
8
9
import { BrowserRouter } from 'react-router-dom';

<BrowserRouter
basename={string}
forceRefresh={bool}
getUserConfirmation={func}
keyLength={number}
>
<App /></BrowserRouter>

basename

所有位置的基准 URL。如果你的应用程序部署在服务器的子目录,则需要将其设置为子目录。basename 的正确格式是前面有一个前导斜杠,但不能有尾部斜杠。

1
2
3
<BrowserRouter basename="/calendar">
<Link to="/today" />
</BrowserRouter>

上例中的 最终将被呈现为:

1
<a href="/calendar/today" />

需要配置服务器

1
2
3
4
5
6
7
8
9
10
11
12
const express = require('express')const path = require('path')const port = process.env.PORT || 8080const app = express()

// 通常用于加载静态资源
app.use(express.static(__dirname + '/public'))

// 在你应用 JavaScript 文件中包含了一个 script 标签// 的 index.html 中处理任何一个 route
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})

app.listen(port)
console.log("server started on port " + port)

Route

无论何时需要在匹配某个路径的时候绘制一个组件,那么就可以使用Route组件。

Route组件可以使用如下的属性:

  • path属性,字符串类型,它的值就是用来匹配url的。
  • component属性,它的值是一个组件。在path匹配成功之后会绘制这个组件。
  • exact属性,这个属性用来指明这个路由是不是排他的匹配。
  • strict属性, 这个属性指明路径只匹配以斜线结尾的路径。

还有其他的一些属性,可以用来代替component属性。

  • render属性,一个返回React组件的方法。传说中的rencer-prop就是从这里来的。
  • children属性,返回一个React组件的方法。只不过这个总是会绘制,即使没有匹配的路径的时候。

大多数情况下你会使用 component。

三种渲染方式都将提供相同的三个路由属性:

  • match
  • location
  • history

URL / Path / Route的参数

指定只有当位置匹配时才会渲染的 React 组件,该组件会接收 route props 作为属性。

1
2
3
4
5
const User = ({ match }) => {
return <h1>Hello {match.params.username}!</h1>
}

<Route path="/user/:username" component={User} />

当你使用 component(而不是 render 或 children)时,Router 将根据指定的组件,使用 React.createElement 创建一个新的 React 元素。这意味着,如果你向 component 提供一个内联函数,那么每次渲染都会创建一个新组件。这将导致现有组件的卸载和新组件的安装,而不是仅仅更新现有组件。当使用内联函数进行内联渲染时,请使用 render 或 children。

match 中包含以下属性

  • url: 匹配的url。
  • path:就是path。
  • isExact:如果path和当前的widnow.location的path部分完全相同的话。
  • params:在URL里包含的参数。

和 exact

渲染第一个被location匹配到的并且作为子元素的或者

不使用

结果:

“/“ -> 页面一
“/second” -> 页面一、页面二

  • “/“只匹配到了path=”/“的所以正常渲染了页面一。
  • “/second”先匹配到了path=”/“的,接着又匹配到了path=”/second/“的,于是把页面一和页面二都渲染了出来。

使用

结果:

“/“ -> 页面一
“/second” -> 页面一

  • 只找到第一个被location匹配到的就立即停止继续匹配,并且把它渲染出来。”/second”同时和”/“,”/second/“相匹配,因为先匹配到了前者,所以只有页面一被渲染。

调整一下顺序:

结果:

“/“ -> 页面一
“/second” -> 页面二

和exact属性结合起来使用:

结果:

“/“ -> 页面一
“/second” -> 页面二

exact 保证只有访问根路径 “/“ 时,该 Route 才会匹配成功

Link组件需要用到to属性,这个属性的值就是react router要跳转到的地址。如:

1
2
3
4
5
import { Link } from 'react-router-dom';

const Nav = () => (
<Link to '/'>Home</Link>
);

to属性的值可以是一个字符串,也可以是一个location(pathname, hash, state和search)对象。比如:

1
2
3
4
5
6
<Link to{{
pathname: '/me',
search: '?sort=asc',
hash: '#hash',
state: { fromHome: true }
}} />

NavLink是Link的一个子类,在Link组件的基础上增加了绘制组件的样式,比如:

1
2
3
<NavLink to="/me" activeStyle={{SomeStyle}} activeClassName="selected">
My Profile
</NavLink>