nature book bug burger costumes doctors hospital office shoes skull rocket

React Router 4 - WEB API

ReactRouter4 的资料太少,结合在官网的学习,做了一份中文文档。

前言

本人英文很差,主要是 Google 翻译稍作修改。但由于网上缺少中文资料,故而做这份文档,方便自己学习和查阅。难免有错误的地方,欢迎批评指正。


React Router 是 React 广泛使用的“路由”库,路由做的事情,可以简单理解为:根据 URL 规则渲染对应的 组件
由于 React 和各个类库迭代频繁,所以网上资料经常过时。在本文编写的 2017年05月08日,以下内容仍是最新的 React Router 4 API。

备注:React Router 4 API 分为 WEB/Native/Core 三部分,以下是 WEB API

目录

官网按照字母顺序罗列(适合查询使用):

<BrowserRouter> (浏览器路由)
- basename: string
- getUserConfirmation: func
- forceRefresh: bool
- keyLength: number
- children: node

<HashRouter> (锚点路由)
- basename: string
- getUserConfirmation: func
- hashType: string
- children: node

<Link> (链接组件)
- to: string
- to: object
- replace: bool

<NavLink> (导航链接组件)
- activeClassName: string
- activeStyle: object
- exact: bool
- strict: bool
- isActive: func

<Prompt> (提示组件)

<MemoryRouter> (内存路由)
- initialEntries: array
- initialIndex: number
- getUserConfirmation: func
- keyLength: number
- children: node

<Redirect> (重定向组件)
- to: string
- to: object
- push: bool
- from: string

<Route> (路由组件)
- component
- render: func
- children: func
- path: string
- exact: bool
- strict: bool

<Router> (路由器组件)
- history: object
- children: node

<StaticRouter> (静态路由组件)
- basename: string
- location: string
- location: object
- context: object
- children: node

<Switch> (单匹配组件)
- children: node

BrowserRouter

<BrowserRouter> (浏览器路由)

使用 HTML5 History API(pushState,replaceState 和 popstate 事件)的 <Router> 来保持 UI 与 URL 同步。

import { BrowserRouter } from 'react-router-dom'

<BrowserRouter
  basename={optionalString}
  forceRefresh={optionalBool}
  getUserConfirmation={optionalFunc}
  keyLength={optionalNumber}
>
  <App/>
</BrowserRouter>

basename: string


所有位置的基本URL。如果您的应用程序是从服务器上的子目录提供的,则需要将其设置为子目录。正确格式化的基本名称应该有一个主要的斜杠,但没有尾部斜杠。

<BrowserRouter basename="/calendar"/>
<Link to="/today"/> // 渲染成 <a href="/calendar/today">

getUserConfirmation: func


用于 确认导航(confirm navigation) 的功能。默认使用 window.confirm。

/*
this is the default behavior
这是默认行为
*/
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<BrowserRouter getUserConfirmation={getConfirmation}/>

forceRefresh: bool


如果为 true,则路由器将在页面导航中使用全页刷新。您可能只希望在不支持 HTML5 History API 的浏览器中使用此功能。

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

keyLength: number


location.key 的长度(默认为6)

<BrowserRouter keyLength={12}/>

children: node


渲染简单的单个子元素

HashRouter

<HashRouter> (锚点路由)

使用 URL 的哈希部分(即 window.location.hash)的 <Router> 来保持您的 UI 与 URL 同步。

重要说明:哈希历史记录不支持 location.keylocation.state。 在以前的版本中,我们试图缓和行为,但是有一些边缘案例我们无法解决。 任何需要此行为的代码或插件将无法正常工作。 由于此技术仅用于支持旧版浏览器,因此我们建议您将服务器配置为使用 <BrowserHistory>。

import { HashRouter } from 'react-router-dom'

<HashRouter>
  <App/>
</HashRouter>

basename: string


所有位置的基本URL。正确格式化的基本名称应该有一个主要的斜杠,但没有尾部斜杠。

<HashRouter basename="/calendar"/>
<Link to="/today"/> // renders <a href="#/calendar/today">

getUserConfirmation: func


用于确认导航的功能。默认使用 window.confirm。

// this is the default behavior
// 这是默认行为
const getConfirmation = (message, callback) => {
  const allowTransition = window.confirm(message)
  callback(allowTransition)
}

<HashRouter getUserConfirmation={getConfirmation}/>

hashType: string


用于 window.location.hash 的编码类型。可用值为:

  • “slash” - 创建像 ‘#/‘ 或是 ‘#/sunshine/lollipops’ 的哈希路径
  • “noslash” - 创建像 ‘#’ 或是 ‘#sunshine/lollipops’ 的哈希路径
  • “hashbang” - 创建 “可抓取的 ajax” (被 Google 弃用)像 ‘#!/‘ 或是 ‘#!/sunshine/lollipops’ 的哈希路径
    默认是 “slash”.

children: node


渲染简单的单个子元素

<Link> (链接组件)

在应用程序周围提供声明性,可访问的导航。(其实,就是有状态的 A 标签。)

import { Link } from 'react-router-dom'

<Link to="/about">About</Link>


链接到的路径名或路径

<Link to="/courses"/>


要链接的位置,接受一个 {} 描述,可带 ‘pathname/search/hash/state’

<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: { fromDashboard: true }
}}/>


如果为 true,单击链接将替换历史堆栈中的当前条目,而不是添加新条目

<Link to="/courses" replace />

<NavLink> (导航链接组件)

一个特殊版本的 <Link>,当与当前 URL 匹配时,将向渲染元素添加样式属性。

import { NavLink } from 'react-router-dom'

<NavLink to="/about">About</NavLink>


当活动时给出元素的 class。默认给定 class 是活动的。这将与 className 支持相结合

<NavLink
  to="/faq"
  activeClassName="selected"
>FAQs</NavLink>


当元素处于活动状态时应用于元素的样式

<NavLink
  to="/faq"
  activeStyle={{
    fontWeight: 'bold',
    color: 'red'
   }}
>FAQs</NavLink>


当为 true 时,仅当位置匹配完全时才会应用 class/style

<NavLink
  exact
  to="/profile"
>Profile</NavLink>


当为 true 时,在确定位置是否与当前网址匹配时,将考虑位置路径名上的尾部斜线。有关详细信息,请参阅 <Route strict>文档

<NavLink
  strict
  to="/events/"
>Events</NavLink>


该功能可以添加额外的逻辑,用于确定是否该链路是活动的。

// only consider an event active if its event id is an odd number
// 只有当事件ID为奇数时, 才考虑事件的激活
const oddEvent = (match, location) => {
  if (!match) {
    return false
  }
  const eventID = parseInt(match.params.eventID)
  return !isNaN(eventID) && eventID % 2 === 1
}

<NavLink
  to="/events/123"
  isActive={oddEvent}
>Event 123</NavLink>

Prompt

<Prompt> (提示组件)

重定向到核心 API 的 Prompt

MemoryRouter

<MemoryRouter> (内存路由)

将 “URL” 的历史记录保存在内存中(不读取或写入地址栏)的 <Router>。在测试和非浏览器环境(如React Native)中很有用。

import { MemoryRouter } from 'react-router'

<MemoryRouter>
  <App/>
</MemoryRouter>

initialEntries: array


历史堆栈中的一系列位置。这些可能是具有 { pathname, search, hash, state } 或简单字符串 URL 的完整位置对象。

<MemoryRouter
  initialEntries={[ '/one', '/two', { pathname: '/three' } ]}
  initialIndex={1}
>
  <App/>
</MemoryRouter>

initialIndex: number


initialEntries 数组中的初始位置索引

getUserConfirmation: func


用于确认导航的功能。使用 <MemoryRouter> 直接使用 <Prompt> 时,必须使用此选项。

keyLength: number


location.key 的长度(默认为6)

<MemoryRouter keyLength={12}/>

children: node


渲染简单的单个子元素

Redirect

<Redirect> (重定向组件)

渲染 <Redirect> 将导航到新的位置。新位置将覆盖历史堆栈中的当前位置,例如服务器端重定向(HTTP 3xx)

import { Route, Redirect } from 'react-router'

<Route exact path="/" render={() => (
  loggedIn ? (
    <Redirect to="/dashboard"/>
  ) : (
    <PublicHomePage/>
  )
)}/>

to: string


要重定向到的网址

<Redirect to="/somewhere/else"/>

to: object


重定向到的位置

<Redirect to={{
  pathname: '/login',
  search: '?utm=your+face',
  state: { referrer: currentLocation }
}}/>

push: bool


当为 true 时,重定向会将新条目推入历史记录,而不是替换当前条目

<Redirect push to="/somewhere/else"/>

from: string


要重定向的路径名。这只能用于在 <Switch> 中渲染 <Redirect> 时匹配位置。有关详细信息,请参阅 <Switch children>

<Switch>
  <Redirect from='/old-path' to='/new-path'/>
  <Route path='/new-path' component={Place}/>
</Switch>

Route

<Route> (路由组件)

Route 组件可能是 React Router 中了解和学习使用的最重要的组件。其最基本的责任是在位置与 location 的路径匹配时呈现一些 UI。

请参阅以下代码:

import { BrowserRouter as Router, Route } from 'react-router-dom'

<Router>
  <div>
    <Route exact path="/" component={Home}/>
    <Route path="/news" component={NewsFeed}/>
  </div>
</Router>

如果应用程序的位置是 ‘/then’ UI 层次结构将是这样的:

<div>
  <Home/>
  <!-- react-empty: 2 -->
</div>

如果应用程序的位置是 ‘/news’,那么 UI 层次结构将是:

<div>
  <!-- react-empty: 1 -->
  <NewsFeed/>
</div>

“react-empty” 的注释只是 React 的 零渲染(null rendering) 的实现细节。 但为了我们的目的,这是有启发性的。 即使其渲染为空,路由总是在技术上“渲染”。 一旦应用位置与路线的路径相符,您的组件将被渲染。

Route render methods


有 3 种方法可以使用 <Route> 来呈现某些东西:

每个在不同的情况下都是有用的。您只能在给定的 <Route> 上使用其一。请参阅下面的解释了解为什么您有 3 个选项。大多数时候你会使用组件。

Route props


所有三种渲染方法都将通过相同的三个路由参数

component


仅当位置匹配时才呈现的 React 组件

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

const User = ({ match }) => {
  return <h1>Hello {match.params.username}!</h1>
}

当您使用组件(而不是下面的渲染)时,路由器使用 React.createElement 从给定组件创建一个新的 React 元素。
这意味着如果您提供内联函数,那么您将在每个渲染中创建一个新组件。 这将导致现有组件卸载和新组件安装,而不是仅更新现有组件。 对于内联渲染,请使用渲染参数(下面)。

render: func


这允许方便的在线渲染和包装,接收一个函数直接返回 JSX(不要和 component 同时使用)

您可以使用组件支持为您创建一个新的 React element,而不必在位置匹配时传入要调用的函数。渲染参数接收与构建渲染参数相同的所有路径参数。

/*
convenient inline rendering
方便内联渲染
*/
<Route path="/home" render={() => <div>Home</div>}/>

// wrapping/composing
const FadingRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    <FadeIn>
      <Component {...props}/>
    </FadeIn>
  )}/>
)

<FadingRoute path="/cool" component={Something}/>

警告:<Route component> 取决于 <Route render>,所以不要在同一个 <Route> 中使用两者。

children: func
根据是否有匹配来渲染

有时您需要渲染路径是否匹配该位置。在这些情况下,您可以使用函数子参数。它的工作原理就像渲染,除了它被调用检查是否有匹配。

子渲染参数接收与组件和渲染方法相同的 route 参数,除非路由未能匹配 URL,则 match 为 null。这允许您根据 route 是否匹配来动态调整您的UI。在这里,如果 route 匹配,我们添加一个活动类。

<ul>
  <ListItemLink to="/somewhere"/>
  <ListItemLink to="/somewhere-else"/>
</ul>

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

这也可以用于动画:

<Route children={({ match, ...rest }) => (
  {/*
    Animate will always render, so you can use lifecycles to animate its child in and out
    动画将始终渲染,所以您可以使用生命周期来使其 子元素 进出动画
  */}
  <Animate>
    {match && <Something {...rest}/>}
  </Animate>
)}/>

警告:<Route component><Route render> 都会超过 <Route children>,所以不要在同一个 <Route> 中使用多个。

path: string


有效的路径,指定路由的匹配规则。这个属性是可以省略的,这样的话,不管路径是否匹配,总是会加载指定组件。

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

没有 path 的 Route 总是匹配。

exact: bool


当为 true 时,只有路径匹配 location.pathname 才匹配。

<Route exact path="/one" component={About}/>
path location.pathname exact matches
/one /one/two true no
/one /one/two false yes

strict: bool


当为 true 时,具有尾部斜杠的路径将仅与具有尾部斜杠的 location.pathname 匹配。当 location.pathname 中有其他URL段时,这不起作用。

<Route strict path="/one/" component={About}/>
path location.pathname matches
/one/ /one no
/one/ /one/ yes
/one/ /one/two yes

警告:strict 可以用来强制一个 location.pathname 没有尾部斜杠,但为了做到这一点,exact 和 matches 必须是 true。

<Route exact strict path="/one" component={About}/>
path location.pathname matches
/one /one yes
/one /one/ no
/one /one/two no

Router

<Router> (路由器组件)

所有路由器组件的常见低级接口。通常,应用程序将使用其中一个高级路由器:

使用低级 <Router> 的最常见用例,是将自定义历史记录与状态管理库(如 Redux 或 Mobx)进行同步。请注意,这不是与 React Router 一起使用状态管理库,这只适用于深度集成。

import { Router } from 'react-router'
import createBrowserHistory from 'history/createBrowserHistory'

const history = createBrowserHistory()

<Router history={history}>
  <App/>
</Router>

history: object


用于导航的历史(history)对象

import createBrowserHistory from 'history/createBrowserHistory'

const customHistory = createBrowserHistory()
<Router history={customHistory}/>

children: node


渲染简单的单个子元素

<Router>
  <App/>
</Router>

StaticRouter

<StaticRouter> (静态路由组件)

一个从不改变位置的 <Router>,区别相对于动态路由。

当用户实际上没有点击时,这在服务器端渲染场景中很有用,因此该位置从未实际更改。 因此,名称:static。 当您只需要插入一个位置并在渲染输出上作出断言时,它也可用于简单的测试。

以下是一个示例节点服务器,为 <Redirect> 发送 HTTP 302 状态代码(Temporarily Moved 暂时性转移重定向),并为其他请求发送常规 HTML。

import { createServer } from 'http'
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { StaticRouter } from 'react-router'

createServer((req, res) => {

  /*
  This context object contains the results of the render
  此上下文对象包含渲染的结果
  */
  const context = {}

  const html = ReactDOMServer.renderToString(
    <StaticRouter location={req.url} context={context}>
      <App/>
    </StaticRouter>
  )

  /*
  context.url will contain the URL to redirect to if a <Redirect> was used
  如果使用了 <Redirect>,则 context.url 将包含要重定向到的 URL
  */
  if (context.url) {
    res.writeHead(302, {
      Location: context.url
    })
    res.end()
  } else {
    res.write(html)
    res.end()
  }
}).listen(3000)

basename: string


所有位置的基本 URL。正确格式化的基本名称应该有一个主要的斜杠,但没有尾部斜杠

<StaticRouter basename="/calendar">
  <Link to="/today"/> // 渲染成 <a href="/calendar/today">
</StaticRouter>

location: string


服务器接收到的URL,可能在 node 服务上 req.url。

<StaticRouter location={req.url}>
  <App/>
</StaticRouter>

location: object


形成一个 location 对象,像 { pathname, search, hash, state }

<StaticRouter location={{ pathname: '/bubblegum' }}>
  <App/>
</StaticRouter>

context: object


一个简单的 JavaScript 对象。在渲染过程中,组件可以添加对象的属性来存储有关渲染的信息。

const context = {}
<StaticRouter context={context}>
  <App />
</StaticRouter>

<Route> 匹配时,它会将 context 对象传递给它作为 staticContext 参数呈现的组件。查看 服务器渲染指南-英文(Server Rendering guide),了解有关如何自行执行此操作的更多信息。

渲染后,这些属性可用于配置服务器的响应。

if(context.status === '404') {
  // ...
}

children: node


渲染简单的单个子元素

Switch

<Switch> (单匹配组件)

渲染与位置匹配的第一个子标签,<Route><Redirect> . 比起 Route’s 他是独特的,只会渲染第一个匹配。

这不同于仅仅使用一堆 <Route>

<Switch> 是独特的,因为它仅仅渲染一个路由。相反,与位置匹配的每个 <Route> 都会包含渲染。参考这个代码:

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

如果 URL 是 ‘/about’,那么 <About><User><NoMatch> 将全部渲染,因为它们都与路径匹配。这是通过设计,允许我们以许多方式将 <Route> 组合到我们的应用程序中,如侧边栏和面包屑,引导选项卡等。

但是,偶尔,我们只想选择一个 <Route> 来渲染。如果我们在 ‘/about’ 不希望也匹配 ‘/:user’(或显示我们的”404页面”)。以下是使用 Switch 的方法:

import { Switch, Route } from 'react-router'

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

现在,如果我们在 ‘/about’,<Switch> 将开始寻找匹配的 <Route><Route path="/about" /> 将匹配,<Switch> 将停止寻找匹配并呈现 <About>。同样,如果我们在 ‘/michael’,那么 <User> 将呈现。

这对于 动画转换(animated transitions) 也是有用的,因为匹配的 <Route> 被渲染在与前一个相同的位置。

<Fade>
  <Switch>
    {/*
    there will only ever be one child here
    这里只会有一个孩子
    */}
    <Route/>
    <Route/>
  </Switch>
</Fade>

<Fade>
  <Route/>
  <Route/>
  {/*
  there will always be two children here, one might render null though, making transitions a bit more cumbersome to work out
  这里有两个孩子,一个可能渲染为 null,从而使转换更加麻烦
  */}
</Fade>

children: node


<Switch> 的所有子项应为 <Route><Redirect> 元素。只有匹配当前位置的第一个子标签才会渲染。

<Route> 元素使用它们的路径匹配匹配,并且 <Redirect> 元素使用它们与参数相匹配。没有路径的路由或路由不正确的 <Redirect> 将始终与当前位置匹配。

当您在 <Switch> 中包含 <Redirect> 时,可以使用任何 <Route> 的位置匹配参数:path,exact 和 strict。从只是 路径参数 的别名。

<Switch>
  <Route exact path="/" component={Home}/>

  <Route path="/users" component={Users}/>
  <Redirect from="/accounts" to="/users"/>

  <Route component={NoMatch}/>
</Switch>

参考资料