react-16-router-V5

112 阅读3分钟

react-router-V5

一、路由模式

import {
  HashRouter as RouterMode,  // 路由别名
  Route,
  Switch,
  Redirect,
  NavLink
} from "react-router-dom"

HashRouter 表示hash模式的路由,有#号

BrowserRouter 表示history模式的路由,没有#号

二、Switch

Switch 组件可以用来包裹Route组件,这样匹配到路由之后,就不会继续匹配了。如果不使用该组件包裹,则会在匹配到之后,继续向下匹配。

<Switch>
    <Route path="/login" component={Login}></Route>
    <Route path="/home" component={Home}></Route> 
    <Redirect from="*" to="/login"></Redirect>
    <Route component={NotFound}></Route>
</Switch>

三、Route 的属性

render 属性里面可以是一个函数,参数props可以提供history的路由相关的方法。在这个函数中可以做一些路由判断等,比如路由鉴权。

<Route
    path="/home"
    render={(props) => {
        console.log(props)
    }}
    ></Route>

exact 精确匹配,这个参数不能设置在有子路由的组件上,否则子路由不生效。

<Route path="/home" component={Home} exact></Route>

四、重定向-Redirect

<Redirect from="*" to="/login"></Redirect>  

五、404组件

万能匹配

<Route component={NotFound}></Route>

六、路由嵌套

一级路由是Home组件

<Route path="/home" component={Home} ></Route>

二级路由写在Home组件里面的对应位置即可

<Switch>
    <Route path="/home/page-a" component={PageA}></Route>
    <Route path="/home/page-b" component={PageB}></Route>
    <Redirect from="/home" to="/home/page-a"></Redirect>
</Switch>

七、声明式与编程式导航

声明式导航

a 标签也可以,但是设置高亮很麻烦

<a href="#/home">home</a>
<a href="#/login">login</a>

内置active类名,直接设置高亮即可

<NavLink to="/home">home</NavLink>
<NavLink to="/login">login</NavLink>

编程式导航

1. js方式
import React from "react"
const Item = () => {
  return (
    <div>
      Item
      <button
        onClick={() => {
          window.location.hash = "#/login"
        }}
      >
        跳转
      </button>
    </div>
  )
}

export default Item
2. 使用 props

被路由相关组件包裹的组, 可以直接通过this.props.history 进行调用相关方法。

<RouterMode>
    <Switch>
        <Route path="/login" component={Login}></Route>
        <Route path="/home" component={Home}></Route>
        <Redirect from="*" to="/login"></Redirect>
        <Route component={NotFound}></Route>
    </Switch>
</RouterMode>
import React, { Component } from "react"

export default class Login extends Component {
  render() {
    console.log(this.props.history)   
    return <div>Login</div>
  }
}
import React from "react"

const Home = (props) => {
  console.log(">>>", props)  // 这个props 因为被route组件包裹,所以存在hsitory对象
  return (
    <div>
      Home
      <Item />
    </div>
  )
}
export default Home
withRouter

某些情况下,我们需要跳转,但是又拿不到history对象,需要使用高阶组件 withRouter 给需要路由跳转的组件添加history对象

import React from "react"
import { withRouter } from "react-router-dom"
const Item = (props) => {
  console.log(props)
  return <div>Item</div>
}

export default withRouter(Item)
3. 使用 useHistory
import { useHistory } from "react-router-dom"

const Home = () => {
  const history = useHistory()

  return (
    <div>
      <button
        onClick={() => {
          history.replace("/home/page-b")
        }}
      >
        按钮
      </button>
      Home
      <Switch>
        <Route path="/home/page-a" component={PageA}></Route>
        <Route path="/home/page-b" component={PageB}></Route>
        <Redirect from="/home" to="/home/page-a"></Redirect>
      </Switch>
    </div>
  )
}

八、动态路由

<RouterMode>
    <Switch>
        // 这里设置的就是动态路由
        <Route path="/login/:id" component={Login}></Route>
        <Route path="/home" component={Home}></Route>
        <Redirect from="*" to="/login"></Redirect>
        <Route component={NotFound}></Route>
    </Switch>
</RouterMode>
// 编程式导航跳转
<button
    onClick={() => {
        history.replace("/login/123")
    }}
    >
    按钮--go-login
</button>

// 声明式导航跳转
  <NavLink to="/login/123">login</NavLink>

跳转到login页面的时候,可以在props里面的match里面的params里面拿到,实现路由传参。

九、路由传参

<Route path="/login" component={Login}></Route>
query 传参

通过这个传参方式,可以在history.location.query 里面获取到参数。

history.replace({ pathname: "/login", query: { id: 123 } })
history.push({ pathname: "/login", query: { id: 123 } })
this.props.history.replace({ pathname: "/login", query: { id: 123 } })
this.props.history.push({ pathname: "/login", query: { id: 123 } })
state 传参

通过这个传参方式,可以在history.location.state里面获取到参数。

history.replace({ pathname: "/login", state: { id: 123 } })
history.push({ pathname: "/login", state: { id: 123 } })
this.props.history.replace({ pathname: "/login", state: { id: 123 } })
this.props.history.push({ pathname: "/login", state: { id: 123 } })

十、路由传参的方案总结

1. 动态路由

<Route path="/login/:id" component={Login}></Route>
<NavLink to="/login/123">login</NavLink>

<button
    onClick={() => {
        history.replace("/login/123")
    }}
    >
    按钮--go-login
</button>

备注:推荐使用,分享链接,参数不会丢失

2. query传参

history.replace({ pathname: "/login", query: { id: 123 } })
history.push({ pathname: "/login", query: { id: 123 } })

备注:参数保存在内存中,分享链接会丢失

3. state传参

history.replace({ pathname: "/login", state: { id: 123 } })
history.push({ pathname: "/login", state: { id: 123 } })

备注:参数保存在内存中,分享链接会丢失

十一、路由拦截

这种做法比较麻烦

<Route
    path="/login"
    render={() => {
        let token = sessionStorage.getItem("TOKEN")
        return token ? <Home /> : <Redirect to="/login"></Redirect>
    }}
    ></Route>

使用路由的鉴权组件

import React from "react"
import { Redirect } from "react-router-dom"

const IsAuth = (props) => {
  let token = sessionStorage.getItem("TOKEN")
  return token ? props.children : <Redirect to="/login"></Redirect>
}
export default IsAuth
<Route
    path="/home"
    render={() => (
        <IsAuth>
            <Home />
        </IsAuth>
    )}
    ></Route>