web前端React文章收藏HTML5学习知识

初探 React Router 4.0

2017-04-04  本文已影响44931人  梁相辉

React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件。所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编程简单来讲就是你只需要关心做什么,而无需关心如何去做,好比你写 React 组件,只需要 render 出你想要的组件,至于组件是如何实现的是 React 要处理的事情。),可组合性的特点。

v4 中文博客介绍
v3 如何迁徙到 v4
v4 代码分割(异步加载)
v4 代码分割辅助库 react-loadable
v4 完全指南

RR4 本次采用单代码仓库模型架构(monorepo),这意味者这个仓库里面有若干相互独立的包,分别是:

本文主要讨论在 web app 中如何使用使用 RR4。

引用

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 分别是:

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)历史的管理。

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

history 对象通常具有以下属性和方法:

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 对象

location 对象不会发生改变,因此可以在生命周期的回调函数中使用 location 对象来查看当前页面的访问地址是否发生改变。这种技巧在获取远程数据以及使用动画时非常有用

componentWillReceiveProps(nextProps) {
  if (nextProps.location !== this.props.location) {
    // 已经跳转了!
  }
}

可以在不同情境中使用 location:

match

match 对象包含了 <Route path> 如何与 URL 匹配的信息,具有以下属性:

在以下情境中可以获取 match 对象

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

上一篇下一篇

猜你喜欢

热点阅读