React 路由

安装:

npm i react-router-dom@4.3.1

index.js 引入相关模块,并设定好 BrowserRouter

// index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom'; // 路由相关模块
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,

  document.getElementById('root')
  );

registerServiceWorker();




设置基础路由

现在 App 组件是 BrowserRouter 的子组件,我们到 App.js 设置相关的路由:

// App.js

import React, { Component } from "react";
import { Route } from 'react-router-dom';  // 路由相关模块

import Products from "./components/products";
import Posts from "./components/posts";
import Home from "./components/home";
import Dashboard from "./components/admin/dashboard";

class App extends Component {
  render() { 
    return (  
      <div>
        <Route path='/products' component={Products}/>
        <Route path='/posts' component={Posts}/>
        <Route path='/dashboard' component={Dashboard}/>
        <Route path='/' component={Home}/>
      </div>
    );
  }
}
 
export default App;

我们有 ProductsPostsHome, Dashboard 四个组件,分别对应各自匹配的路由规则。

Route 组件中 path 参数表示 URL 的匹配规则,component 参数表示对应渲染的组件。

如:访问 /products 的 URL 时会渲染 Products 组件。




路由匹配规则

以上路由会出现一个 URL 同时符合多个匹配规则的问题,比如访问 /products 时,会同时匹配到 / 对应的 Home/products 对应的 Products。如何让解决这个问题呢?

首先路由的算法是检测 URL 是否以给定规则为开头,比如: /products 这个规则,既能匹配到 /products 也能匹配到 /products/abc

要解决该问题的第一个方法是使用 exact 属性:

<Route path='/products' component={Products}/>
<Route path='/posts' component={Posts}/>
<Route path='/dashboard' component={Dashboard}/>
<Route path='/' exact component={Home}/>

使用 exact 属性后 / 规则只匹配 URL 为 / 的情况。

第二种方法是使用 Switch 组件:

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

<Switch>
  <Route path='/products' component={Products}/>
  <Route path='/posts' component={Posts}/>
  <Route path='/dashboard' component={Dashboard}/>
  <Route path='/' component={Home}/>
</Switch>

Switch 会匹配第一条符合的子规则。所以 Router 的排列需要按照从最特殊到最一般的顺序。




Route 的 Props 属性

我们进入 /products 的 URL 看看渲染出来的 Products 组件有什么属性。

可以看到有 historylocationmatch 三个属性。这三个属性是 RouteProducts 添加的。(这三个属性的作用详细看官方文档:https://reacttraining.com/react-router/web/api/Route/route-props

  • history 记录了浏览器的访问记录,可以实现页面退回等功能。

  • location 记录的是当前页面。

  • match 记录 URL 匹配规则。




添加额外的 Props 属性

现在我要为 Products 加入一个 sortBy 属性,我们使用 Routerender 参数配合箭头函数来操作:

{/* 使用箭头函数传递参数,记得要把原来的 props 参数也传入 */}
<Route 
  path='/products' 
  render={(props) => <Products sortBy='newest' {...props} />} 
/>

现在 Products 属性除了自带的三个属性外还有了我们新增的 sortBy 属性。




通过 URL 传递参数

假设我们引入 ProductDetails 组件来渲染某个 product,我们使用 id 来作为区分每个 product 的依据。

Routepath 参数中使用冒号来表示 URL 参数:

<Route path='/products/:id' component={ProductDetails}/>
<Route 
  path='/products' 
  render={(props) => <Products sortBy='newest' {...props} />} 
/>

这里需要注意 Route 是从上往下只要匹配第一条符合规则的原则,所以更为特殊的规则:/products/:id 应当放在更一般的规则 /products 上方。

那么现在我们可以在 ProductDetails 读取来自 URL 的参数 id。它在 this.props.match.params.id 里面。




可选的 URL 参数

在 Route 的 path 参数中使用问号来表示可选的 URL 参数:

<Route path='/posts/:month?/:year?' component={Posts}/>

现在 monthyear 两个参数均为可选。参数存放于 this.props.match.params 中。




get 方法传递参数

HTTP 的 GET 方法允许我们通过 URL 传递参数,例如:/posts?year=2019&month=06。像 ?year=2019&month=06 这种方法又叫查询字符串。

它们存放在 props.loaction.search 中。

手动读取这个查询字符集比较麻烦,我们安装 query-string 包来帮助我们更方便地去处理这些参数。

npm i query-string@6.1.0

使用方法:

import queryString from 'query-string';

const result = queryString.parse(this.props.location.search);

console.log(result);
// {month: "06", year: "2019"}

注意,转换的结果都是字符串,如果有需要请转会成对应的数据类型。




重定向

使用 Redirect 组件来重定向网页,我们把该组件放在最下方,当所有匹配规则都查找过一遍都没有符合的时候网页就会被重定向到 /not-found 页面。

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

……………………
<Route path='/not-found' component={NotFound} />
<Route path='/' exact component={Home}/>
<Redirect to='/not-found' />

Redirect 组件有 fromto 两个属性,可以定义从哪个页面跳转到指定页面的功能。

<Redirect from='/messages' to='/posts' />

当访问 /message 页面时候就会被跳转到 /posts

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

推荐阅读更多精彩内容