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;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本项目Github地址,欢迎star 目录 这部分API文档翻译参考了项目react-router-CN < Br...
    Harlan_Zhang阅读 5,449评论 0 1
  • React项目的可用的路由库React-Router,当然这也是官方支持的。它也分为:*react-router ...
    落寒_49c6阅读 4,811评论 0 0
  • React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的。它也分...
    橙不懂柠檬酸z阅读 461评论 0 0
  • 渐变的面目拼图要我怎么拼? 我是疲乏了还是投降了? 不是不允许自己坠落, 我没有滴水不进的保护膜。 就是害怕变得面...
    闷热当乘凉阅读 9,770评论 0 13
  • 感觉自己有点神经衰弱,总是觉得手机响了;屋外有人走过;每次妈妈不声不响的进房间突然跟我说话,我都会被吓得半死!一整...
    章鱼的拥抱阅读 6,551评论 4 5