08.路由

react-router-4官方文档
demo的github源码地址
URL
一个URL可以定位到网络上的指定资源。一个典型URL结构如下:

url.jpeg

虽然protocol和hostname的组合可以直接让我们访问特定的网站,但是pathname则代表的是这个网站上的指定资源。

举个例子,看看如下的一个访问音乐网站的URL
https://example.com.com/artists/87589/albums/1758221

这个地址可以访问特定艺术家的专辑。该URL包含了艺术家以及它的专辑的标识符:
example.com/artists/:artistId/albums/:albumId

在一个传统的,只有很少的JavaScript的页面应用中,对网页访问的请求流程大致如下:

  1. 浏览器要访问页面,向服务器发送请求
  2. 服务器根据URL中的标识符从数据库中获取artist和album的数据
  3. 服务器将获取后的数据拼接成模板
  4. 服务器返回模板字符串,并且返回其关联的资源文件,例如CSS文件和图片文件等
  5. 浏览器将得到的资源渲染

当我们使用React,我们想要React来生成这样的页面。所以,使用React的请求流程就会大致如下:

  1. 浏览器要访问页面,向服务器发送请求
  2. 服务器不关心pathname。取而代之的是,它仅仅返回一个标准的index.html,其中包含了React app和其他静态资源文件
  3. React app 挂载
  4. React app抽取出URL中标识符,并且使用这些标识符来生成API调用以从artist和album中获取数据
  5. React根据API调用后抓取的数据渲染页面

单页应用(Single-page applications/ SPA)是加载一次然后通过JavaScript动态更新页面上的元素的应用。React通过路由能够很容易的实现单页应用。


实现
首先生成我们的demo,一个新闻页面切换的app
create-react-app react-router-demo
并且成功运行项目。
目录结构如下:

content.jpeg

要使用React的路由功能,需要安装依赖react-router。这里我们使用第四个版本的 react-router
安装依赖:
yarn add react-router-dom
或者
npm install --save react-router-dom

在router.js中:

import React from 'react';
import {BrowserRouter, Route, Link} from 'react-router-dom'

import News from '../components/News'
import NBA from '../components/NBA'
import Economics from '../components/Economic'

const router = (
  <BrowserRouter>
    <div>
      <h2>news app</h2>
      <ul>
        <li>
          <Link to="/">news</Link>
        </li>
        <li>
          <Link to="/nba">nba</Link>
        </li>
        <li>
          <Link to="/economics">economics</Link>
        </li>
      </ul>
      <Route path="/" component={News} exact></Route>
      <Route path="/nba" component={NBA}></Route>
      <Route path="/economics" component={Economics}></Route>
    </div>
  </BrowserRouter>
)

export default router

然后点击对应的链接就能切换响应的页面了。
现在需要点击对应的链接后,能够有一个显示点击后的效果。这个时候就需要使用NavLink了。
如下:

    <style>
      .is-active {
        font-weight: bold;
        color: deepskyblue;
      }
    </style>

const router = (
  <BrowserRouter>
    <div>
      <h2>news app</h2>
      <ul>
        <li>
          <NavLink to="/" activeClassName="is-active" exact>news</NavLink>
        </li>
        <li>
          <NavLink to="/nba" activeClassName="is-active">nba</NavLink>
        </li>
        <li>
          <NavLink to="/economics" activeClassName="is-active">economics</NavLink>
        </li>
      </ul>
      <Route path="/" component={News} exact></Route>
      <Route path="/nba" component={NBA}></Route>
      <Route path="/economics" component={Economics}></Route>
    </div>
  </BrowserRouter>
)

这样,点击对应的链接后,该链接会显示style中的样式。

当用户输入错了URL地址,我们希望能够跳转到一个页面不存在的通用的页面。我们新建一个NotFound的组件,再在路由中是 Switch。表示只要匹配到第一个就跳转到对应组件。

const router = (
  <BrowserRouter>
    <div>
      <h2>news app</h2>
      <ul>
        <li>
          <NavLink to="/" activeClassName="is-active" exact>news</NavLink>
        </li>
        <li>
          <NavLink to="/nba" activeClassName="is-active">nba</NavLink>
        </li>
        <li>
          <NavLink to="/economics" activeClassName="is-active">economics</NavLink>
        </li>
      </ul>
      <Switch>
        <Route path="/" component={News} exact></Route>
        <Route path="/nba" component={NBA}></Route>
        <Route path="/economics" component={Economics}></Route>
        <Route component={NotFound}></Route>
      </Switch>
    </div>
  </BrowserRouter>
)

这样,当用户虽然输入一个URL地址后,只要没有匹配到前面的路由地址,那么就会跳转到NotFound页面。


路由参数
当我们想要访问一个新闻列表的页面,新闻列表中有很多个新闻,我们点击其中的新闻,则URL地址可能如下:
localhost:3000/news/1
localhost:3000/news/2
localhost:3000/news/3

当有大量新闻的时候,为每个新闻都写一个组件显然是不显示的。这时候就可以使用路由参数。

router.js

const router = (
  <BrowserRouter>
    <div>
      <h2>news app</h2>
      <ul>
        <li>
          <NavLink to="/" activeClassName="is-active" exact>news</NavLink>
        </li>
        <li>
          <NavLink to="/nba" activeClassName="is-active">nba</NavLink>
        </li>
        <li>
          <NavLink to="/economics" activeClassName="is-active">economics</NavLink>
        </li>
      </ul>
      <Switch>
        <Route path="/" component={News} exact></Route>
        <Route path="/nba" component={NBA}></Route>
        <Route path="/economics" component={Economics}></Route>
        <Route path="/newslist/:id" component={NewsList}></Route>
        <Route component={NotFound}></Route>
      </Switch>
    </div>
  </BrowserRouter>
)

NewsList.js

class NewsList extends Component {
  render () {
    return (
      <div>
        newslist-item {this.props.match.params.id}
      </div>
    )
  }
}

这样,主要输入形如如下的网址,那么就可以切换到不同的NewsList中的新闻了:
localhost:3000/news/id

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,392评论 25 707
  • 版权声明:本文为博主原创文章,未经博主允许不得转载。 PS:转载请注明出处作者:TigerChain地址:http...
    TigerChain阅读 22,976评论 3 49
  • 原文链接:https://github.com/halfrost/Halfrost-Field/blob/mast...
    hament阅读 5,638评论 1 31
  • 我希望,我感动自己的时候,不只是话出口的一瞬间,又或者是在虚无的幻境之中
    Cheer_up阅读 105评论 0 0