ReactRouter4

# Hello

路由是根据不同的网址显示不同的组件,并有一系列API的封装

import React from 'react';
import { HashRouter as Router, Link, Route } from "react-router-dom"

const Home = () => <h1>首页</h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <h1>用户</h1>;

function App() {

  return (
    <>
      <Router>
        <Link to="/">首页</Link>
        <Link to="/pro">产品</Link>
        <Link to="/user">用户</Link>
        <Route path="/" exact component={Home} />
        <Route path="/pro" component={Prod} />
        <Route path="/user" component={User} />
      </Router>
    </>
  )
}

export default App;

Link 的 to 属性就是要跳转的路由

Rote 中的 path 对应 to ,表示要渲染的组件

exact 表示完全匹配,如果没有,那么 / 或匹配 /* 而不是 /

# Router

组成

BrowserRouter

HashRouter

MemoryRouter

NativeRouter

StaticRouter

其中 BrowserRouter 和 HashRouter 属于浏览器路由

浏览器路由

BrowserRouter 的路由类似 http://localhost:3000/user

HashRouter 的路由类似 http://localhost:3000/#/user

属性

pathname 路由的地址其实是 pathname + path

比如 Router 加上 pathname="api"

使用前:http://localhost:3000/#/user

使用后:http://localhost:3000/#/api/user

<Router basename="/api">
  <Link to="/">首页</Link>
  <Link to="/pro">产品</Link>
  <Link to="/user">用户</Link>
  <Route path="/" exact component={Home} />
  <Route path="/pro" component={Prod} />
  <Route path="/user" component={User} />
</Router>

forceRefresh 布尔值,是否刷新整个页面,如果为 true ,每次跳转路由都会刷新页面

<Router forceRefresh={true}>
  <Link to="/">首页</Link>
  <Link to="/pro">产品</Link>
  <Link to="/user">用户</Link>
  <Route path="/" exact component={Home} />
  <Route path="/pro" component={Prod} />
  <Route path="/user" component={User} />
</Router>

getUserConfirmation 当导航需要确认时执行的函数,需配合 Prompt 使用

Prompt 写在需要提示的路由中,也可不写 getUserConfirmation ,如果不写,默认是window弹框

写了 getUserConfirmation 后,可以在处理跳转前的逻辑

import React from 'react';
import { HashRouter as Router, Link, Route, Prompt } from "react-router-dom"

const Home = () => <h1>首页<Prompt message="您是否离开首页?"></Prompt></h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <h1>用户</h1>;

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

function App() {

  return (
    <>
      <Router getUserConfirmation={getConfirmation}>
        <Link to="/">首页</Link>
        <Link to="/pro">产品</Link>
        <Link to="/user">用户</Link>
        <Route path="/" exact component={Home} />
        <Route path="/pro" component={Prod} />
        <Route path="/user" component={User} />
      </Router>
    </>
  )
}

export default App;

hashType HashRouter独有,一共有三个值

slash #/api/user

noslash #api/user

hashbang #!/api/user

# Link

属性 to

路由跳转地址,可以是字符串

<Link to="/user">用户</Link>

可是是对象

<Link to={{
  pathname:"/user"
}}>用户</Link>

对象有如下属性:

pathname 跳转地址

search 参数传递

hash 跳转的锚点

state 状态,可以通过 params.location.state 获取

const User = (params) => {
  return params.location.state ? <h1>{params.location.state.name}</h1> : null;
}

属性 replace

布尔值,如果为 true,则访问历史替换原地址

如果为false(默认),访问历史记录添加一项

<Link to="/user" replace />

# NavLink

特殊的 Link

如果在当前路由状态,会默认的添加一个 active 样式

属性:

activeStyle 如果在当前路由状态,可以添加额外的style

activeClassName 如果在当前路由状态,可以添加额外的 class 并替换 active

exact 完全匹配 activeStyle 和 activeClassName 才会生效

# Route

三种使用方式

使用component,默认把参数传到组件中

<Link to="/">首页</Link>

const Home = (props) => {
  console.log(props);
  return <h1>首页</h1>;
}

使用 render ,需自行把参数添加到组件中

const Prod = (props) => {
  console.log(props);
  return <h1>产品</h1>;
}

<Route path="/pro" render={(props) => <Prod {...props}></Prod>} />

使用 children,每次都会执行,有一个参数 match 可以判断是否是指定路由

const User = (props) => {
  console.log(props);
  return <h1>用户</h1>;
}

<Route path="/user" children={(props) => {
  return props.match ? <User {...props}></User> : null;
}} />

match

先看一下 match 的结构

{
    isExact: true,
    params: { id: "2" },
    path: "/pro/:id",
    url: "/pro/2"
}

isExact 是否全匹配

params 参数

path 匹配路径格式

url 匹配路径

作用一: 路由参数

可以使用 props.match.params 获取参数

import React from 'react';
import { HashRouter as Router, Link, Route } from "react-router-dom"

const Home = () => <h1>首页</h1>;
const User = () => <h1>用户</h1>;

const ProdDetail = (props) => <p>产品:{props.match.params.id}</p>;

const Prod = () => {
  return (
    <>
      <Link to="/pro/1">产品1</Link>
      <Link to="/pro/2">产品2</Link>
      <Link to="/pro/3">产品3</Link>
      <Route path="/pro/:id" component={ProdDetail}></Route>
    </>
  )
}

function App() {

  return (
    <>
      <Router basename="/api">
        <Link to="/">首页</Link>
        <Link to="/pro">产品1</Link>
        <Link to="/user">用户</Link>

        <Route path="/" component={Home} exact />
        <Route path="/pro" component={Prod} />
        <Route path="/user" component={User} />
      </Router>
    </>
  )
}

export default App;

作用二:变量提取

const Prod = (props) => {
  const basePath = props.match.url;
  return (
    <>
      <Link to={`${basePath}/1`}>产品1</Link>
      <Link to={`${basePath}/2`}>产品2</Link>
      <Link to={`${basePath}/3`}>产品3</Link>
      <Route path={`${basePath}/:id`} component={ProdDetail}></Route>
    </>
  )
}

location

可以拿到 Link:to 中的内容,如果是字符串则拿不到 state

<Link to={
  {
    pathname: "/user",
    hash: "#h1",
    search: "?name=lisi",
    state: { name: "张三" }
  }
}>用户</Link>

const User = ({ location }) => {
  console.log(location);
  return <h1>用户</h1>;
}

// 得到的结果为

{
  hash: "#h1",
  pathname: "/user",
  search: "?name=lisi",
  state: { name: "张三" }
}

history

操作路由的一些 API ,可以从传递的参数中解构获取

const User = ({ history }) => {
  console.log(history);
  return <h1>用户</h1>;
}

属性:

length 堆栈数量

action 当前动作,是跳转过来的(PUSH),还是切换过来的(REPLACE)还是移出的(POP)

方法:

push 跳转路由

replace 替换栈顶路由

go 前进或后退多少路由

goBack 后退1步,相当于 go(-1)

goForward 前进一步,相当于 go(1)

block 阻止跳转

# Redirect

重定向到新的地址

import React from 'react';
import { HashRouter as Router, Link, Route, Redirect } from "react-router-dom"

const Home = () => <h1>首页</h1>;
const Prod = () => <h1>产品</h1>;
const User = () => <Redirect to="/pro"></Redirect>;

function App() {

  return (
    <>
      <Router basename="/api">
        <Link to="/">首页</Link>
        <Link to="/pro">产品</Link>
        <Link to="/user">用户</Link>

        <Route path="/" component={Home} exact />
        <Route path="/pro" component={Prod} />
        <Route path="/user" component={User} />
      </Router>
    </>
  )
}

export default App;

此时点用户,会被重定向到产品路由

常用作配合状态使用,当状态更新时,重定向到其他路由,比如登出

import React, { useState } from 'react';
import { HashRouter as Router, Link, Route, Redirect } from "react-router-dom"

const Home = () => {
  const [isLogin, setisLogin] = useState(true);
  return (
    isLogin ?
      <>
        <h1>恭喜xx登录成功!</h1>
        <p onClick={() => setisLogin(false)}>登出</p>
      </> :
      <Redirect to="/login"></Redirect>
  )
};
const Login = () => {
  return (
    <>
      <h1>登录页</h1>
      <button>登录</button>
    </>
  )
};

function App() {

  return (
    <>
      <Router basename="/api">
        <Link to="/">首页</Link>

        <Route path="/" component={Home} exact />
        <Route path="/login" component={Login} />
      </Router>
    </>
  )
}

export default App;

# Switch

未使用 Switch 前,一个地址可以匹配多个路径

比如以下代码,路径 /pro 可匹配 / 和 /pro ,除非给 Route 加上 exact

<>
  <Router basename="/api">
    <Link to="/">首页</Link>
    <Link to="/pro">产品</Link>
    <Link to="/user">用户</Link>

    <Route path="/" component={Home}></Route>
    <Route path="/pro" component={Prod}></Route>
    <Route path="/user" component={User}></Route>
  </Router>
</>

使用 Switch 之后,只会匹配到遇到的第一个路由

比如以下代码,无论是 / 还是 /pro 还是 /user 都是匹配到了首页

<>
  <Router basename="/api">
    <Link to="/">首页</Link>
    <Link to="/pro">产品</Link>
    <Link to="/user">用户</Link>
    <Switch>
      <Route path="/" component={Home}></Route>
      <Route path="/pro" component={Prod}></Route>
      <Route path="/user" component={User}></Route>
    </Switch>
  </Router>
</>

弱匹配的路由放在后面或者加上 exact 属性

<>
  <Router basename="/api">
    <Link to="/">首页</Link>
    <Link to="/pro">产品</Link>
    <Link to="/user">用户</Link>
    <Switch>
      <Route path="/pro" component={Prod}></Route>
      <Route path="/user" component={User}></Route>
      <Route path="/" component={Home}></Route>
    </Switch>
  </Router>
</>

Switch 配合 404 页面

<>
  <Router basename="/api">
    <Link to="/">首页</Link>
    <Link to="/pro">产品</Link>
    <Link to="/user">用户</Link>
    <Switch>
      <Route path="/pro" component={Prod}></Route>
      <Route path="/user" component={User}></Route>
      <Route path="/" component={Home} exact></Route>
      <Route component={View404}></Route>
    </Switch>
  </Router>
</>

# Prompt

组件确认跳转导航,在路由离开之前弹框,如果点击是,则跳转,否则不跳转

import React from 'react';
import { HashRouter as Router, Link, Route, Switch, Prompt } from "react-router-dom"

const Home = () => <h1>Home! <Prompt message="是否离开首页!"></Prompt></h1>;
const User = () => <h1>User!</h1>;
const Prod = () => <h1>Prod!</h1>;

function App() {

  return (
    <>
      <Router basename="/api">
        <Link to="/">首页</Link>
        <Link to="/pro">产品</Link>
        <Link to="/user">用户</Link>
        <Switch>
          <Route path="/pro" component={Prod}></Route>
          <Route path="/user" component={User}></Route>
          <Route path="/" component={Home} exact></Route>
        </Switch>
      </Router>
    </>
  )
}

export default App;

当首页跳转其他页时,会提示是否离开首页,如果选是,则离开,否则不离开

message 还可以是一个函数,返回结果作为提示语,函数的参数的location

const Home = () => <h1>Home! <Prompt message={
  (location) => {
    return `是否离开首页,去${location.pathname}`
  }
}></Prompt></h1>;

Prompt 还有一个属性,when,默认为 true , 如果为false,则不提示直接跳转

const Home = () => <h1>Home! <Prompt when={false} message={
  (location) => {
    return `是否离开首页,去${location.pathname}`
  }
}></Prompt></h1>;

可以和 getUserConfirmation 配合使用,自定义弹出提示

import React from 'react';
import { HashRouter as Router, Link, Route, Switch, Prompt } from "react-router-dom"

const Home = () => <h1>Home! <Prompt message="是否离开"></Prompt></h1>;
const User = () => <h1>User!</h1>;
const Prod = () => <h1>Prod!</h1>;

const getUserConfirmation = (message, call) => {
  const flag = window.confirm(message);
  call(flag);
}

function App() {

  return (
    <>
      <Router basename="/api" getUserConfirmation={getUserConfirmation}>
        <Link to="/">首页</Link>
        <Link to="/pro">产品</Link>
        <Link to="/user">用户</Link>
        <Switch>
          <Route path="/pro" component={Prod}></Route>
          <Route path="/user" component={User}></Route>
          <Route path="/" component={Home} exact></Route>
        </Switch>
      </Router>
    </>
  )
}

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

推荐阅读更多精彩内容