React Router 4.0 体验

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 保持同步。此组件拥有如下属性:javascript

basename: string
做用:为全部位置添加一个基准URL
使用场景:假如你须要把页面部署到服务器的二级目录,你可使用 basename 设置到此目录。java

<BrowserRouter basename="/minooo" />
<Link to="/react" /> // 最终渲染为 <a href="/minooo/react">

  

getUserConfirmation: func
做用:导航到此页面前执行的函数,默认使用 window.confirm
使用场景:当须要用户进入页面前执行什么操做时可用,不过通常用到的很少。node

const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

 

<BrowserRouter getUserConfirmation={getConfirmation('Are you sure?', yourCallBack)} /> 

  

forceRefresh: bool
做用:当浏览器不支持 HTML5 的 history API 时强制刷新页面。
使用场景:同上。react

const supportsHistory = 'pushState' in window.history
<BrowserRouter forceRefresh={!supportsHistory} />

keyLength: number
做用:设置它里面路由的 location.key 的长度。默认是6。(key的做用:点击同一个连接时,每次该路由下的 location.key都会改变,能够经过 key 的变化来刷新页面。)
使用场景:按需设置。git

<BrowserRouter keyLength={12} />

children: node
做用:渲染惟一子元素。
使用场景:做为一个 Reac t组件,天生自带 children 属性。github

尝试一下npm


<HashRouter>

Hash history 不支持 location.keylocation.state。另外因为该技术只是用来支持旧版浏览器,所以更推荐你们使用 BrowserRouter,此API再也不做多余介绍。编程


<Route>

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

<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 时,它会匹配一切路径。

相关文章
相关标签/搜索