React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步。
目前react-router最新版本已经到4.0+,因为新的版本是一次非常大的改动,所以这里直接讨论4.0以上版本。
引用
react-router // React Router 核心 react-router-dom // 用于 DOM 绑定的 React Router react-router-native // 用于 React Native 的 React Router react-router-redux // React Router 和 Redux 的集成 react-router-config // 静态路由配置的小助手
以上资源库按需引用,本文讨论web端应用,只需要引用react-router-dom即可。(如果需要搭配redux则还需引用react-router-redux)
主要组件
<Route>
Route组件主要的作用就是当一个location匹配路由的path时,渲染某些UI,exp:
1 import { BrowserRouter as Router, Route } from 'react-router-dom' 2 3 <Router> 4 <div> 5 <Route exact path="/" component={Home}/> 6 <Route path="/news" component={NewsFeed}/> 7 </div> 8 </Router> 9 // If the location of the app is / then the UI hierarchy will be something like: 10 11 <div> 12 <Home/> 13 <!-- react-empty: 2 --> 14 </div> 15 // And if the location of the app is /news then the UI hierarchy will be: 16 17 <div> 18 <!-- react-empty: 1 --> 19 <NewsFeed/> 20 </div>
<Route> 的三种渲染方式 :
<Route component> // 只有当访问地址和路由匹配时,一个 React component 才会被渲染,此时此组件接受 route props (match, location, history) <Route render> // 此方法适用于内联渲染,不会引起意料之外的重新挂载 <Route children> // 不管地址匹配与否都会被调用,与render的工作方式基本一样
tips:同一个<Route>中只使用一种渲染方式,多种会被覆盖,优先级为component>render>children。
<Route> 的三个属性:
path(string): // 路由匹配路径。(没有path属性的Route 总是会 匹配); exact(bool): // 为true时,则要求路径与location.pathname必须完全匹配; strict(bool): // 为true时,有结尾斜线的路径只能匹配有斜线的location.pathname
<BrowserRouter>
<Router>
使用 HTML5 提供的 history API (pushState
, replaceState
和 popstate
事件) 来保持 UI 和 URL 的同步。
属性:
basename: string
作用:为所有位置添加一个基准URL(假如你需要把页面部署到服务器的二级目录,你可以使用 basename
设置到此目录)
<BrowserRouter basename="/minooo" /> <Link to="/react" /> // 最终渲染为 <a href="/minooo/react">
getUserConfirmation: func
作用:导航到此页面前执行的函数,默认使用 window.confirm
const getConfirmation = (message, callback) => { const allowTransition = window.confirm(message) callback(allowTransition) } <BrowserRouter getUserConfirmation={getConfirmation('Are you sure?', yourCallBack)} />
forceRefresh: bool
作用:当浏览器不支持 HTML5 的 history API 时强制刷新页面。
const supportsHistory = 'pushState' in window.history <BrowserRouter forceRefresh={!supportsHistory} />
keyLength: number
作用:设置它里面路由的 location.key
的长度。默认是6。(key的作用:点击同一个链接时,每次该路由下的 location.key
都会改变,可以通过 key 的变化来刷新页面。)
<BrowserRouter keyLength={12} />
children: node
作用:渲染单一子元素。
<Link>
为应用提供声明式的、无障碍导航。
import { Link } from 'react-router-dom' <Link to="/about">关于</Link>
属性:
to: string
需要跳转到的路径(pathname)或地址(location)。
<Link to="/courses"/>
to: object
需要跳转到的地址(location)。
<Link to={{ pathname: '/courses', search: '?sort=name', hash: '#the-hash', state: { fromDashboard: true } }}/>
replace: bool
当设置为 true
时,点击链接后将使用新地址替换掉访问历史记录里面的原地址。
当设置为 false
时,点击链接后将在原有访问历史记录的基础上添加一个新的纪录。
默认为 false
。
<NavLink>
<NavLink>
是<Link>
的一个特定版本, 会在匹配上当前 URL 的时候会给已经渲染的元素添加样式参数
属性
activeClassName: string
导航选中激活时候应用的样式名,默认样式名为 active
<NavLink to="/about" activeClassName="selected" >MyBlog</NavLink>
activeStyle: object
如果不想使用样式名就直接写style
<NavLink to="/about" activeStyle={{ color: 'green', fontWeight: 'bold' }} >MyBlog</NavLink>
exact: bool
若为 true,只有当访问地址严格匹配时激活样式才会应用
strict: bool
若为 true,只有当访问地址后缀斜杠严格匹配(有或无)时激活样式才会应用
isActive: func
决定导航是否激活,或者在导航激活时候做点别的事情。不管怎样,它不能决定对应页面是否可以渲染。
<Switch>
只渲染出第一个与当前访问地址匹配的 <Route>
若没有匹配则渲染 <Redirect>
import { Switch, Route } from 'react-router' <Switch> <Route exact path="/" component={Home}/> <Route path="/about" component={About}/> <Route path="/:user" component={User}/> <Redirect to={NoMatch}/> </Switch>
<Redirect>
<Redirect>
渲染时将导航到一个新地址,这个新地址覆盖在访问历史信息里面的本该访问的那个地址。
属性
to: string
重定向的 URL 字符串
to: object
重定向的 location 对象
push: bool
若为真,重定向操作将会把新地址加入到访问历史记录里面,并且无法回退到前面的页面。
from: string
需要匹配的将要被重定向路径。
<Prompt>
当用户离开当前页面前做出一些提示。
属性
message: string
当用户离开当前页面时,设置的提示信息。
<Prompt message="确定要离开?" />
message: func
当用户离开当前页面时,设置的回掉函数
<Prompt message={location => ( `Are you sue you want to go to ${location.pathname}?` )} />
when: bool
通过设置一定条件要决定是否启用 Prompt
对象和方法
history
history 对象通常具有以下属性和方法:
length: number // 浏览历史堆栈中的条目数 action: string // 路由跳转到当前页面执行的动作,分为 PUSH, REPLACE, POP location: object // 当前访问地址信息组成的对象,具有如下属性: pathname: string // URL路径 search: string // URL中的查询字符串 hash: string // URL的 hash 片段 state: string // 例如执行 push(path, state) 操作时,location 的 state 将被提供到堆栈信息里,state 只有在 browser 和 memory history 有效。 push(path, [state]) // 在历史堆栈信息里加入一个新条目。 replace(path, [state]) // 在历史堆栈信息里替换掉当前的条目 go(n) // 将 history 堆栈中的指针向前移动 n。 goBack() // 等同于 go(-1) goForward // 等同于 go(1) block(prompt) // 阻止跳转
history 对象是可变的,因此建议从 <Route>
的 prop 里来获取 location,而不是从 history.location 直接获取。这样可以保证 React 在生命周期中的钩子函数正常执行,exg:
class Comp extends React.Component { componentWillReceiveProps(nextProps) { // locationChanged const locationChanged = nextProps.location !== this.props.location // 错误方式,locationChanged 永远为 false,因为history 是可变的 const locationChanged = nextProps.history.location !== this.props.history.location } }
location
location 是指你当前的位置,将要去的位置,或是之前所在的位置
{ key: 'sdfad1' pathname: '/about', search: '?name=cz' hash: '#af01a', state: { price: 998 } }
在以下情境中可以获取 location 对象
在 Route component 中,以 this.props.location 获取 在 Route render 中,以 ({location}) => () 方式获取 在 Route children 中,以 ({location}) => () 方式获取 在 withRouter 中,以 this.props.location 的方式获取
location 对象不会发生改变,因此可以在生命周期的回调函数中使用 location 对象来查看当前页面的访问地址是否发生改变。这种技巧在获取远程数据以及使用动画时非常有用
componentWillReceiveProps(nextProps) { if (nextProps.location !== this.props.location) { // 已经跳转了! } }
可以在不同情境中使用 location:
<Link to={location} /> <NaviveLink to={location} /> <Redirect to={location /> history.push(location) history.replace(location)
match
match 对象包含了 <Route path> 如何与 URL 匹配的信息,具有以下属性:
params: object // 路径参数,通过解析 URL 中的动态部分获得键值对 isExact: bool // 为 true 时,整个 URL 都需要匹配 path: string // 用来匹配的路径模式,用于创建嵌套的 <Route> url: string // URL 匹配的部分,用于嵌套的 <Link>
获取 match 对象
在 Route component 中,以 this.props.match获取 在 Route render 中,以 ({match}) => () 方式获取 在 Route children 中,以 ({match}) => () 方式获取 在 withRouter 中,以 this.props.match的方式获取matchPath 的返回值