入坑 React-router 4

React-router VS React-router-dom

区别

React-router 提供了一些 router 的核心功能。
React-router-dom 提供浏览器运行环境下的一些功能,用于 DOM 绑定,我们可以通过 DOM 的事件控制路由。

如何选用

react-router-dom 比前者多出了 <Link> <BrowserRouter> 这样的 DOM 类组件。
因此我们只需引用 react-router-dom 这个包就行了。当然,如果搭配 redux ,你还需要使用 react-router-redux

核心

HashRouter和BrowserRouter

HashRouterBrowserRouter 像是一个 box 所有的 route 都需要放在里面。

HashRouter

HashRouter 是通过 hash 值来对路由进行控制。使用 HashRouter,路由会默认有个#。

ReactDOM.render(
  <HashRouter>
    <div>
      <Nav />
      <Route exact path='/' component={Home}></Route>
      <Route path='/game' component={Game}></Route>
    </div>
  </HashRouter>,
  document.getElementById('root')
);

小游戏详见: react 三子棋小游戏

BrowserRouter

BrowserRouter 使用了 HTML5 history API,保证 UI 界面和 URL 保持同步。使用 BrowserRouter ,路由不会有个#。

ReactDOM.render(
  <BrowserRouter>
    <div>
      <Nav />
      <Route exact path='/' component={Home}></Route>
      <Route path='/game' component={Game}></Route>
    </div>
  </BrowserRouter>,
  document.getElementById('root')
);
basename: string

为所有位置添加一个基准URL,当需要把页面部署到服务器的二级目录时,可以使用 basename 设置到此目录。

getUserConfirmation: func

导航到此页面前执行的函数,默认使用 window.confirm (需同 Prompt 配合使用)
此为默认行为

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

// ========================================

ReactDOM.render(
  <BrowserRouter getUserConfirmation={getConfirmation}>
    <div>
      <Prompt message="你确定要离开当前页面吗?" />
      <Nav />
      <Route exact path='/' component={Home}></Route>
      <Route path='/game' component={Game}></Route>
    </div>
  </BrowserRouter>,
  document.getElementById('root')
);

传送门:react-history

forceRefresh: bool

若为 true,导航过程中会刷新整个页面。多在不支持 HTML5 history API 的浏览器中使用此功能。

keyLength: number

设置它里面路由的 location.key 的长度。默认是6。(key:点击同一个链接时, location.key 都会改变。)
this.props.location

children: node

渲染唯一子元素,React组件自带 children 属性。
传送门:https://reactjs.org/docs/react-api.html#react.children.only

Route

控制路径对应显示的组件

ReactDOM.render(
  <BrowserRouter>
    <div>
      <Nav />
      <Route exact path='/' component={Home}></Route>
      <Route path='/game' component={Game}></Route>
    </div>
  </BrowserRouter>,
  document.getElementById('root')
);
Route render methods
  • <Route component>
  • <Route render>
  • <Route children>
    同一个 <Route> 应该只使用一种渲染方法 ,大部分情况下使用 component
component

只有访问地址和路由匹配时,才会渲染 React 组件。Router 将根据指定的组件,使用 React.createElement 创建一个新的 React 元素。(如果你向 component 提供一个内联函数,那么每次渲染都会创建一个新组件,这将产生不必要的重复装载)

render

可以方便地进行内联渲染和包装,而无需进行不必要的组件重装。传入一个函数,在位置匹配时调用,而不是使用 component 创建一个新的 React 元素。

警告:<Route component> 优先于 <Route render>,因此不要在同一个 <Route> 中同时使用两者。

children

无论 path 是否匹配都可以渲染,除此之外,它的工作原理与 render 完全一样。路由与 URL 不匹配时 matchnull。因此,可以根据路由是否匹配,动态地调整用户界面。

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

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

警告:<Route component><Route render> 优先于 <Route children>,因此不要在同一个 <Route> 中同时使用多个。

Route render methods

三种渲染方式都将提供相同的三个路由属性

  • match
  • location
  • history
match

match 是在使用 router 之后被放入 props 中的一个属性,在 class 创建的组件中我们需要通过 this.props.match 来获取 match 之中的信息。

<BrowserRouter>
    <div>
      <Nav />
      <Route exact path='/' component={Home}></Route>
      <Route path='/game/:id' component={Game}></Route>
    </div>
  </BrowserRouter>
history

它提供了很多有用的方法可以在路由系统中使用。

location

它可以认为是 URL 的对象形式表示。

path: string

可以是 path-to-regexp 能够理解的任何有效的 URL 路径。
没有定义 path<Route> 总是会被匹配。

exact: bool

如果为 true,则只有在 path 完全匹配 location.pathname 时才匹配。

exact path location.pathname matches?
true /home /home/list no
false /home /home/list yes
strict: bool

如果为 true,则具有尾部斜杠的 path 仅与具有尾部斜杠的 location.pathname 匹配。

path location.pathname matches?
/home/ /home no
/home/ /home/ yes
/home/ /home/list yes
sensitive: bool

如果为 true,进行匹配时将区分大小写。

sensitive path location.pathname matches?
true /home /home yes
true /Home /home no
false /Home /home yes

Link VS NavLink

两者都是可以控制路由跳转的,而 NavLink 的 api 更多

Link

提供声明式的、可访问的导航链接。

to: string

一个字符串形式的链接地址

<Link to='/courses?sort=name' />
to: object

一个对象形式的链接地址,可以具有以下任何属性:

  • pathname - 要链接到的路径
  • search - 查询参数
  • hash - URL 中的 hash
  • state - 存储到 location 中的额外状态数据
<Link to={{
  pathname: '/courses',
  search: '?sort=name',
  hash: '#the-hash',
  state: {
    fromDashboard: true
  }
}} />
replace: bool

当设置为 true 时,点击链接后将替换历史堆栈中的当前条目,而不是添加新条目。默认为 false。(当点击返回时将找不到设置为 true 的页面)

<Link to='/'>Home</Link>
<Link to='/game' replace>Game</Link>
<Link to='/list'>List</Link>

一次跳转 '/' => '/game' => '/list' => '/'
点击返回 '/' => '/list' => '/'

innerRef: func

允许访问组件的底层引用。

NavLink

一个特殊版的 Link,它会在与当前 URL 匹配时为其呈现元素添加样式属性。(其实就是像为页面导航准备的。因为导航需要有 “activated state”。)

activeClassName: string

当元素处于 activated state 时应用的类,默认为 active。与 className 属性一起使用。

activeStyle: object

当元素处于 activated state 时应用的样式。

exact: bool

如果为 true,则只有在位置完全匹配时才应用 activated 类/样式。

strict: bool

如果为 true,则在确定位置是否与当前 URL 匹配时,路径名后面的斜杠。

isActive: func

添加额外逻辑以确定链接是否处于激活状态的函数。

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>
location: object

isActive 默认比较当前历史位置(通常是当前的浏览器 URL)。你也可以传递一个不同的 location 进行比较。

Prompt

跳转之前的一些确认信息。

message: string

当用户试图离开某个位置时弹出的提示信息。

message: func

将在用户试图导航到下一个位置时调用。需要返回一个字符串以向用户显示提示,或者返回 true 允许直接跳转。

when: bool

在应用程序中,你可以始终渲染 <Prompt> 组件,并通过设置 when={true}when={false} 以阻止或允许相应的提示,而不是根据某些条件来决定是否渲染 <Prompt> 组件。

当它的值为 true 时,会弹出提示信息。如果为 false 则不会弹出。

Redirect

<Redirect> 渲染时将导航到一个新地址,这个新地址覆盖在访问历史信息里面的本该访问的那个地址(类似服务器端重定向)。

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

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

要重定向到的 URL 字符串,可以是 path-to-regexp 能够理解的任何有效的 URL 路径。要使用的 URL 参数必须由 from 提供。

to: object

要重定向到的位置,其中 pathname 可以是 path-to-regexp 能够理解的任何有效的 URL 路径。

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

如果为 true,重定向会将新的位置推入历史记录,而不是替换当前条目。

from: string

将要被重定向路径。所有匹配的 URL 参数都会提供给 to,必须包含在 to 中用到的所有参数,未使用参数将被忽略。只能在 <Switch> 组件内使用 <Redirect from>

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

相当于 Route.exact

strict: bool

相当于 Route.strict

Switch

常常会用来包裹Route,它里面不能放其他元素,用于渲染与路径匹配的第一个子 <Route><Redirect>

这与仅仅使用列表形式的 <Route> 有何不同?

<Switch> 只会渲染一个路由。而单纯的 <Route> 列表,每一个与路径匹配的 <Route> 都将包含在渲染范围内。

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

如果 URL 是 /about,那么 <About><User><NoMatch> 将全部渲染,因为它们都与路径匹配。这将允许我们以很多方式将 <Route> 组合成我们的应用程序,如侧边栏和面包屑、引导标签等。

但如果我们只想选择一个 ·<Route>· 来呈现。比如我们在 URL 为 ·/about· 时不想匹配 /:user,就是可以通过 <Switch> 实现

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

用于匹配子元素而不是当前历史位置(通常是当前的浏览器 URL)的 location 对象。

children: node

所有 <Switch> 的子元素都应该是 <Route><Redirect>。只有第一个匹配当前路径的子元素将被呈现。

<Route> 组件使用 path 属性进行匹配,而 <Redirect> 组件使用它们的 from 属性进行匹配。(没有 path 属性的 <Route> 或者没有 from 属性的 <Redirect> 将始终与当前路径匹配。)

如果给 <Switch> 提供一个 location 属性,它将覆盖匹配的子元素上的 location 属性。

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

官方文档:https://reacttraining.com/react-router/web/api/BrowserRouter
参考链接:
https://blog.csdn.net/sinat_17775997/article/details/69218382
http://react-china.org/t/react-router4/15843
https://segmentfault.com/a/1190000014294604#articleHeader0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容