安装 : npm install react-router-dom

定义路由规则

src/router/index.js

  1. import React from 'react'
  2. import Film from '../views/Film';
  3. ...
  4. //Routes代替了switch
  5. import {Route,Routes} from 'react-router-dom'
  6. export default function MRouter () {
  7. return (
  8. <Routes>
  9. <Route path="/films" element={<Film />} />
  10. <Route path="/cinemas" element={<Cinema />} />
  11. <Route path="/center" element={<Center />} />
  12. </Routes>
  13. )
  14. }

导入路由

App.js

import {HashRouter} from 'react-router-dom'
import MRouter from '../src/router'

function App() {
  return (
    <HashRouter>
      <MRouter></MRouter>
    </HashRouter>
  );
}

export default App;

重定向 & 404

v6没有Redirect,推荐使用Navigate

import React from 'react'
import {Route,Routes,Navigate} from 'react-router-dom'
import Redirect from '../components/Redirect';
import NotFound from '../views/NotFound'

export default function MRouter () {
  return (
    <Routes>
      ...
      //重定向方式一(不推荐) :自定义Redirect组件
      <Route path="/" element={<Redirect to="/films"/>}/>
      //重定向方式二(推荐) :使用Navigate
      <Route path='/' element={<Navigate to="/films"/>}/>

      //404 *匹配所有 该规则要放到最后
      <Route path='*' element={<NotFound/>}/>
    </Routes>
  )
}

Redirect组件

import {useEffect} from 'react'
import { useNavigate } from 'react-router-dom'

export default function Redirect({to}) {
    const navigate = useNavigate()
    useEffect(() => {
        navigate(to,{replace:true})   
    })
    return null
}

嵌套路由

定义

src/router/index.js

export default function MRouter () {
  return (
    <Routes>
      <Route path="/films" element={<Film />} >
        //子路由
        <Route path="nowplaying" element={<Nowplaying/>} />
        <Route path="comingsoon" element={<Comingsoon/>} />
        //index父路径 访问/films时重定向到/films/nowplaying
        <Route index element={<Navigate to="/films/nowplaying"/>}/>
      </Route>
    </Routes>
  )
}

路由容器 & 使用

Film组件

import React from 'react'
import {Outlet} from 'react-router-dom'

export default function Cinema () {
  return (
    <div>
      Filme
      //子路由容器
      <Outlet></Outlet>
    </div>
  )
}

声明式导航与编程式导航useNavigate

声明式: <NavLink to"">
编程式: useNavigate()

声明式跳转传参

import {NavLink} from 'react-router-dom'

export default function Tabbar(){
  return(
    <div>
      <li>
        <NavLink to='/films' className={({isActive})=>isActive?'kerwinactive':''}>电影</NavLink>
      </li>
    </div>
  )
}

编程式导航跳转传参

import {useNavigate} from 'react-router-dom'

//url跳转传参
const navigate = useNavigate()

//指定跳转
navigate(`/detail?id=${id}`)

//replace
navigate('/child1/child1B',{replace: true})

// 历史记录 前进
navigate(1)

// 历史记录 后退
navigate(-1)

// 历史记录 后退两步
navigate(-2)

参数获取

//获取url参数
import { useSearchParams } from 'react-router-dom'
const [searchParams, setSearchParams] = useSearchParams()
// 获取参数
searchParams.get('id')
// 判断参数是否存在
searchParams.has('id')
// 同时页面内也可以用set方法来改变路由
setSearchParams({"id":2})

路由传参

params

params

//params 参数传参路由定义
<Route path="/detail/:myid" element={<Detail />} />

//params传参
const navigate = useNavigate()
navigate(`/detail/${id}`)

//params 参数接收
import { useParams } from 'react-router-dom'
const { myid } =useParams()
console.log(myid);

声明式

需配置路由 /toogle/:id
<Link to={'/toggle/123'}></Link>

query | search

编程式


import { useSearchParams } from 'react-router-dom'

//query 传参
const navigate = useNavigate()
navigate(`/detail?id=${id}`)

//query 参数接收
const [searchParams, setSearchParams]  = useSearchParams()
console.log(searchParams.get('id'));

声明式

不用配置路由
<Link to={'/toggle?age=20&name=zhangsan'}></Link>

state

编程式

//state 传参
const navigate = useNavigate()
navigate("/exam",{state: {...})

//query 参数接收
const location =  useLocation()
console.log(location.state);

声明式

不用配置路由
<Link to={'/toggle'} state= {{title: this.state.exam.title}}></Link>

路由地址 useLocation

const { pathname } = useLocation()

路由拦截

如果跳转到center没有token则去login页面

//路由规则
export default function MRouter () {
  return (
    <Routes>
      //Center组件作为参数传入
      <Route path="/center" element={<AuthComponent><Center /></AuthComponent>} />
      <Route path="/login" element={<Login/>}/>
    </Routes>
  )
}
//是否登录判断逻辑
function AuthComponent({children}){
  const isLogin = localStorage.getItem('token')
  //没有登录则到login
  return isLogin ? children : <Navigate to="/login"/>
}

路由模式

import {HashRouter} from 'react-router-dom'
import {BrowserRouter} from 'react-router-dom'

withRouter / 类组件跳转方法

v6没有withRouter , 实现方法如下:

  1. hooks函数组件可以用const navigate = useNavigate()
  2. 类组件自定义withRouter

    自定义withRouter

import React from 'react'
import {
    useNavigate,
    useParams,
    useLocation
}from 'react-router-dom'

export default function withRouter(Component) {
    return function(props){
        const push =  useNavigate()
        const match =  useParams()
        const location =  useLocation()
        //props 将组件原有的props返回 同时增加history
        return <Component  {...props} history={{push,match,location}}/>
    }
}

使用

import React, { Component } from 'react'
import withRouter from '../../components/withRouter'

class FilmItem extends Component {
    render() {
        return (
            <li onClick={()=>this.handleClick(this.props.filmId)}>
                {this.props.name}
            </li>
        )
    }

    handleClick(id){
        // console.log(this.props.history)
        this.props.history.push(`/detail/${id}`)

        // this.props.history.push 跳转页面
        // this.props.history.match 获取参数
        // this.props.history.location 获取当前路由
    }
}

export default withRouter(FilmItem)//****

路由懒加载

import React from 'react'
import {Route,Routes,Navigate} from 'react-router-dom'
// import Cinema from '../views/Cinema';

export default function MRouter () {
  return (
    <Routes>
      {/* <Route path="/cinemas" element={<Cinema />} /> */}
      //定义规则
      <Route path="/cinemas" element={LazyLoad("Cinema")} />
    </Routes>
  )
}

//懒加载函数
const LazyLoad = (path) => {
  const Comp = React.lazy(() => import(`../views/${path}`))
  return ( //必须要借助React.Suspense
      <React.Suspense fallback={<>加载中...</>}>
          <Comp />
      </React.Suspense>
  )
}

useRoutes钩子配置路由

像vue一样配置路由 src/router/index.js

import React from 'react'
import {useRoutes} from 'react-router-dom'
import Redirect from '../components/Redirect';

export default function MRouter() {
    const element = useRoutes([
        {
            path:"/films",
            //懒加载
            element:LazyLoad("Film"),
            //子路由
            children:[
                {
                    path:"",
                    element:<Navigate to="/films/nowplaying"/>
                }
            ]
        },
        {
            path:"/center",
            //路由拦截
            element:<AuthComponent>
                        {LazyLoad("Center")}
                    </AuthComponent>
        },
        {
            path:"/",
            element:<Navigate to="/films"/> //默认路由
        },
        {
            path:"*",
            element:LazyLoad("NotFound") //404
        }
    ])
    //将组件路由规则返回
    return (
       element
    )
}

//路由拦截组件的封装
function AuthComponent({children}){}

//路由懒加载的封装
const LazyLoad = (path)=>{}