React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编程简单来讲就是你只需要关心做什么,而无需关心如何去做,好比你写 React 组件,只需要 render 出你想要的组件,至于组件是如何实现的是 React 要处理的事情。),可组合性的特点。、
RR4 本次采用单代码仓库模型架构(monorepo),这意味者这个仓库里面有若干相互独立的包,分别是:
  • 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 静态路由配置的小助手

引用

react-router 还是 react-router-dom?

在 React 的使用中,我们一般要引入两个包,reactreact-dom,那么 react-routerreact-router-dom 是不是两个都要引用呢?
非也,坑就在这里。他们两个只要引用一个就行了,不同之处就是后者比前者多出了 <Link> <BrowserRouter> 这样的 DOM 类组件。
因此我们只需引用 react-router-dom 这个包就行了。当然,如果搭配 redux ,你还需要使用 react-router-redux
what is the diff between react-router-dom & react-router?

组件

<BrowserRouter>

一个使用了 HTML5 history API 的高阶路由组件,保证你的 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
作用:渲染唯一子元素。
使用场景:作为一个 Reac t组件,天生自带 children 属性。

尝试一下


<HashRouter>

Hash history 不支持 location.keylocation.state。另外由于该技术只是用来支持旧版浏览器,因此更推荐大家使用 BrowserRouter,此API不再作多余介绍。


<Route>

<Route> 也许是 RR4 中最重要的组件了,重要到你必须理解它,学会它,用好它。它最基本的职责就是当页面的访问地址与 Route 上的 path 匹配时,就渲染出对应的 UI 界面。

<Route> 自带三个 render method 和三个 props 。

render methods 分别是:

  • <Route component>
  • <Route render>
  • <Route children>
    每种 render method 都有不同的应用场景,同一个<Route> 应该只使用一种 render method ,大部分情况下你将使用 component

props 分别是:

  • match
  • location
  • history
    所有的 render method 无一例外都将被传入这些 props。

component
只有当访问地址和路由匹配时,一个 React component 才会被渲染,此时此组件接受 route props (match, location, history)。
当使用 component 时,router 将使用 React.createElement 根据给定的 component 创建一个新的 React 元素。这意味着如果你使用内联函数(inline function)传值给 component 将会产生不必要的重复装载。对于内联渲染(inline rendering), 建议使用 render prop。

<Route path="/user/:username" component={User} />
const User = ({ match }) => {
return <h1>Hello {match.params.username}!</h1>
}

render: func
此方法适用于内联渲染,而且不会产生上文说的重复装载问题。

// 内联渲染
<Route path="/home" render={() => <h1>Home</h1} /> // 包装 组合
const FadingRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={props => (
<FadeIn>
<Component {...props} />
</FaseIn>
)} />
) <FadingRoute path="/cool" component={Something} />

children: func
有时候你可能只想知道访问地址是否被匹配,然后改变下别的东西,而不仅仅是对应的页面。

<ul>
<ListItemLink to="/somewhere" />
<ListItemLink to="/somewhere-ele" />
</ul> const ListItemLink = ({ to, ...rest }) => (
<Route path={to} children={({ match }) => (
<li className={match ? 'active' : ''}>
<Link to={to} {...rest} />
</li>
)}
)

path: string
任何可以被 path-to-regexp解析的有效 URL 路径

<Route path="/users/:id" component={User} />

如果不给path,那么路由将总是匹配。

exact: bool
如果为 true,path 为 '/one' 的路由将不能匹配 '/one/two',反之,亦然。

strict: bool
对路径末尾斜杠的匹配。如果为 true。path 为 '/one/' 将不能匹配 '/one' 但可以匹配 '/one/two'。

如果要确保路由没有末尾斜杠,那么 strict 和
exact 都必须同时为 true

尝试一下


<Link>

为你的应用提供声明式,无障碍导航。

to: string
作用:跳转到指定路径
使用场景:如果只是单纯的跳转就直接用字符串形式的路径。

<Link to="/courses" />

  

to: object
作用:携带参数跳转到指定路径
作用场景:比如你点击的这个链接将要跳转的页面需要展示此链接对应的内容,又比如这是个支付跳转,需要把商品的价格等信息传递过去。

<Link to={{
pathname: '/course',
search: '?sort=name',
state: { price: 18 }
}} />

replace: bool
为 true 时,点击链接后将使用新地址替换掉上一次访问的地址,什么意思呢,比如:你依次访问 '/one' '/two' '/three' ’/four' 这四个地址,如果回退,将依次回退至 '/three' '/two' '/one' ,这符合我们的预期,假如我们把链接 '/three' 中的 replace 设为 true 时。依次点击 one two three four 然后再回退会发生什么呢?会依次退至 '/three' '/one'! 为此我做了个在线 demo,大家可以调试体会一下 !

另外你能想到这个 prop 的用途是什么呢?有人说在用 路由 做选项卡时候会用到。欢迎留言讨论!

尝试一下


<NavLink>

这是 <Link> 的特殊版,顾名思义这就是为页面导航准备的。因为导航需要有 “激活状态”。

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>

思考如下代码,如果你访问 /about,那么组件 About User Nomatch 都将被渲染出来,因为他们对应的路由与访问的地址 /about 匹配。这显然不是我们想要的,我们只想渲染出第一个匹配的路由就可以了,于是 <Switch> 应运而生!

<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>

也许你会问,为什么 RR4 机制里不默认匹配第一个符合要求的呢,答:这种设计允许我们将多个 <Route> 组合到应用程序中,例如侧边栏(sidebars),面包屑 等等。

另外,<Switch> 对于转场动画也非常适用,因为被渲染的路由和前一个被渲染的路由处于同一个节点位置!

<Fade>
<Switch>
{/* 用了Switch 这里每次只匹配一个路由,所有只有一个节点。 */}
<Route/>
<Route/>
</Switch>
</Fade> <Fade>
<Route/>
<Route/>
{/* 不用 Switch 这里可能就会匹配多个路由了,即便匹配不到,也会返回一个null,使动画计算增加了一些麻烦。 */}
</Fade> 

children: node
<Switch> 下的子节点只能是 <Route><Redirect> 元素。只有与当前访问地址匹配的第一个子节点才会被渲染。<Route> 元素用它们的 path 属性匹配,<Redirect> 元素使用它们的 from 属性匹配。如果没有对应的 pathfrom,那么它们将匹配任何当前访问地址。

尝试一下


<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

histoty 是 RR4 的两大重要依赖之一(另一个当然是 React 了),在不同的 javascript 环境中, history 以多种能够行驶实现了对会话(session)历史的管理。

我们会经常使用以下术语:

  • "browser history" - history 在 DOM 上的实现,用于支持 HTML5 history API 的浏览器
  • "hash history" - history 在 DOM 上的实现,用于旧版浏览器。
  • "memory history" - history 在内存上的实现,用于测试或非 DOM 环境(例如 React Native)。

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 在生命周期中的钩子函数正常执行,例如以下代码:

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=minooo'
hash: '#sdfas',
state: {
price: 123
}
}

在以下情境中可以获取 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 的返回值

当一个 Route 没有 path 时,它会匹配一切路径。

React Router 4.0 体验的更多相关文章

  1. react router 4.0以上的路由应用

    thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr& ...

  2. React Router 4.0 实现路由守卫

    在使用 Vue 或者 Angular 的时候,框架提供了路由守卫功能,用来在进入某个路有前进行一些校验工作,如果校验失败,就跳转到 404 或者登陆页面,比如 Vue 中的 beforeEnter 函 ...

  3. 初步学习React Router 4.0

      React Router 4.0 是react官方推荐的路由库.4是已经正式发布的最新版本. 初始化项目启动之后: npm run eject 弹出配置文件.自定义配置webpack 查看下pac ...

  4. React Router 4.0 + webpack 实现组件按需加载

    网上关于React Router 4.0的按需加载文章有很多,大致的思路都一样,但是其实具体实现起来却要根据自己的实际情况来定,这里主要介绍一下我的实现方式. 主要方式是通过Route组件的rende ...

  5. React Router V4.0学习笔记

    最近在学习React Router,但是网站的教程多半还是3.X版本之前的,所以我只能在GitHub上找到React Router的官方文档在读.后来总结了一下,包括学习经验以及V3.X与V4.X的差 ...

  6. React Router 4.0 基本使用

    路由的概念,起初来源于服务端,就是当浏览器访问一个网站的不同页面时,服务端能够正确的返回页面的内容.当访问首页时,它能返回首页的内容,访问关于我们页面时,返回关于我们的内容.可以看到路由就是一种控制和 ...

  7. React Router 4.0 ---- 嵌套路由和动态路由

    嵌套路由,从广义上来说,分为两种情况:一种是每个路由到的组件都有共有的内容,这时把共有的内容抽离成一个组件,变化的内容也是一个组件,两种组件组合嵌套,形成一个新的组件.另一种是子路由,路由到的组件内部 ...

  8. React Router 4.0中文快速入门

    import React from 'react' import { BrowserRouter as Router, Route, Link } from 'react-router-dom' co ...

  9. 【共享单车】—— React后台管理系统开发手记:Router 4.0路由实战演练

    前言:以下内容基于React全家桶+AntD实战课程的学习实践过程记录.最终成果github地址:https://github.com/66Web/react-antd-manager,欢迎star. ...

随机推荐

  1. 告诉你一些DBA求职面试技巧

    告诉你一些DBA求职面试技巧 要自信!永远不要低估你的能力.如果你不了解什么问题的答案,承认它.重点放在你找出答案的能力和你学习的意愿. 不要自大!是的,你可能过于自信而被认为是骄傲的.轻率的,甚至是 ...

  2. [日常] 小白来装机基本概念BIOS与硬盘分区

    这两天因为在linux进行测试,先是搞坏了linux的系统,然后在重装linux系统后搞坏了引导.在修复引导的过程中,搞坏了本机的win8系统,再次修复引导与重装linux后,linux可以访问了,w ...

  3. C++中的异常处理(下)

    array.h #ifndef _ARRAY_H_ #define _ARRAY_H_ #include <stdexcept> using namespace std; template ...

  4. Oracle SQL日期及日期格式获取命令

    日期及日期格式: 获取系统日期: sysdate() 格式化日期 to_char(sysdate(),'yyyy-mm-dd,hh24:mi:ss') to_date(sysdate(),'yyyy- ...

  5. Mybatis动态SQL(五)

    if choose (when, otherwise) trim (where, set) foreach 一.if 动态SQL通常要做的事情是有条件地包含 where 子句的一部分.比如: < ...

  6. (day49)Django框架简介

    目录 一.Web框架 (一)本质 (1)动静态网页 (2)wsgiref模块 (3)jinja2模块 (4)手动实现思路 (二)python主流框架 (1)Django (2)flask (3)tor ...

  7. shellnet运行train_val_seg.py

    1.semantic3d数据集准备:prepare_semantic3d_data.py 11个测试数据集(.txt文件): 假如运行的是室外点云数据集“seg_semantic3d”,可能需要做以下 ...

  8. luoguP2824 [HEOI2016/TJOI2016]排序(二分答案做法)

    题意 这题的思路实在巧妙. 首先我们肯定无法对区间进行sort,那么考虑如何使得sort简化. 问:如果给的序列是一个0-1序列,让你区间排序,那么怎么做? 答:建一颗线段树维护sum,求出当前区间中 ...

  9. luoguP2597 [ZJOI2012]灾难

    题意 这题思路好奇怪啊 见到有向无环图显然是要拓朴排序,不妨按照被吃向吃连边,那么\(x\)灭绝当且仅当x的入点都灭绝,于是考虑怎样x的入点都灭绝 比如4号节点,它灭绝当且仅当2和3灭绝,2和3灭绝当 ...

  10. 学习:反调试之IsDebuggerPresent

    前言:一个反调试IsDebuggerPresent的CreackMe IsDebuggerPresent函数的了解: IsDebuggerPresent 作用 确定调用进程是否由用户模式的调试器调试. ...