React18路由详解


1. 改变了什么

  1. 推荐使用函数组件
  2. 使用Routes替换原来的Switch组件
  3. 使用Navigate组件替换原来的Redirect组件
  4. Route组件必须包裹在Routes组件里
  5. 路由规则是严格匹配,匹配成功就不向下继续匹配
  6. 定义路由规则匹配渲染组件语法改变component/render/children => element={<名称 />}
  7. 新增了多个hook函数,useParams、useSearchParams、useNavigate、useRoutes等

2. 路由安装和定义路由规则

安装:

yarn add react-router-dom@6

使用:

  1. 在 src/index.js 文件中定义当前项目所使用的路由模式

    import React from 'react'
    import ReactDOM from 'react-dom/client'
    import App from './App'
    
    // 定义当前项目的路由模式
    import {
          
           BrowserRouter as Router } from 'react-router-dom'
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <Router>
        <App />
      </Router>
    );
    
  2. 在 src/App.jsx 组件中定义路由规则

    import React from 'react'
    // 定义路由规则
    import {
          
           Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'
    // Route用来定义路由规则的,它一定要在Routes组件中包裹起来,否则报错
    
    // 路由匹配成功后要渲染的组件
    import Home from './views/Home'
    import About from './views/About'
    
    const App = () => {
          
          
      return (
        <div>
          <Routes>
            <Route path='/' element={
          
          <Home />} />
            <Route path='/about' element={
          
          <About />} />
          </Routes>
        </div>
      )
    }
    
    export default App
    

在这里插入图片描述

3. 声明式导航

import React from 'react'
// 定义路由规则
import {
    
     Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'
// Route用来定义路由规则的,它一定要在Routes组件中包裹起来,否则报错
// Link, NavLink 用于声明式导航,它们编译为html都为a标签,NavLink有激活样式

// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'

const App = () => {
    
    
  return (
    <div>
      {
    
    /* 声明式导航 */}
      <div>
        {
    
    /* 
          to 指定跳转到的路由地址
          state 对象,隐式传递数据
          replace boolean 是否可以回退
          end它是5版本中的exact 严格匹配 ==> / 就是最后,后面没有匹配内容  boolean
          激活样式默认的名称为active,如果你想修改它,则需要通过className={isActive=>isActive?'aa':''}
        */}
        {
    
    /* 对于首页导航自定义激活样式名称 */}
        {
    
    /* <NavLink end to="/" className={isActive => (isActive ? 'myactive' : '')}> */}
        {
    
    /* end={true}等价于end */}
        <NavLink end to="/" state={
    
    {
    
     id: 1000 }}>首页</NavLink>
        <span> --- </span>
        <NavLink to="/about">关于</NavLink>
      </div>
      <hr />
      <Routes>
        <Route path='/' element={
    
    <Home />} />
        <Route path='/about' element={
    
    <About />} />
      </Routes>
    </div>
  )
}

export default App

在这里插入图片描述

重定向和404:

import React from 'react'
// 定义路由规则
import {
    
     Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'

// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'

const App = () => {
    
    
  return (
    <div>
      {
    
    /* 声明式导航 */}
      <div>
        <NavLink end to="/home" state={
    
    {
    
     id: 1000 }}>首页</NavLink>
        <span> --- </span>
        <NavLink to="/about">关于</NavLink>
      </div>
      <hr />
      <Routes>
        <Route path='/home' element={
    
    <Home />} />
        <Route path='/about' element={
    
    <About />} />
        {
    
    /* 重定向 */}
        <Route path="/" element={
    
    <Navigate to="/home" replace={
    
    false} />} />
        {
    
    /* 404页面处理 */}
        <Route path="*" element={
    
    <div>没有页面</div>} />
      </Routes>
    </div>
  )
}

export default App

在这里插入图片描述

4. 编程式导航

关于组件:

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

const About = () => {
    
    
  const navigate = useNavigate()
  return (
    <div>
      <h3>关于我们</h3>
      <hr />
      <button
        onClick={
    
    () => {
    
    
          // 回退
          navigate(-1)
        }}
      >
        回到首页
      </button>
    </div>
  )
}

export default About

首页组件:

import React from 'react'
// 编程式导航,需要用到hook函数来得到导航对象,完成编程导航
import {
    
     NavLink, useNavigate } from 'react-router-dom'

const Home = () => {
    
    
  const navigate = useNavigate()

  const jumpUrl = () => {
    
    
    // 写法1
    // 参数1:string/number  string它就是一个url地址,number就是回退的步数 正向前 负向后
    // 参数2:对象,可选,可以不写
    // navigate('/about', {
    
    
    //   state: {}, // 隐式传递数据
    //   replace: true // 不可回退
    // })

    // 写法2
    navigate('/about')
  }

  return (
    <div>
      <h3>首页页面</h3>
      <hr />
      <button onClick={
    
    jumpUrl}>跳转到关于页面</button>
    </div>
  )
}

export default Home

在这里插入图片描述

5. 页面参数获取

import React from 'react'
import {
    
     useLocation, useParams, useSearchParams } from 'react-router-dom'
// useParams 获取动态路由参数
// useSearchParams 获取search字符串
// useLocation location对象,可以得到state数据,得到pathname,得到search字符串

const Detail = () => {
    
    
  const location = useLocation()
  const params = useParams()
  // search它是一个对象,URLSearchParams对象,可以用里面的get方法获取search中的字段数据
  // setSearch 可以动态的修改当前search字符串中的字段数据,一般用不到
  const [search, setSearch] = useSearchParams()
  // 一般情况下是这种写法
  // const [search] = useSearchParams()

  return (
    <div>
      <h3>页面详情</h3>
      <div>动态路由参数id:{
    
    params.id}</div>
      <div>state中的数据:{
    
    location.state?.name}</div>
      <div>search字符串中的age:{
    
    search.get('age')}</div>
      <button
        onClick={
    
    () => {
    
    
          // 修改之后state中的数据会丢失
          setSearch('?age=100')
        }}
      >
        修改search字符串
      </button>
    </div>
  )
}

export default Detail

在这里插入图片描述

6. 嵌套路由

父组件:

import React from 'react'
// 定义路由规则
import {
    
     Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'

// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'
import Detail from './views/Detail'
import Admin from './views/Admin'
import Welcome from './views/Welcome'
import User from './views/User'

const App = () => {
    
    
  return (
    <div>
      {
    
    /* 声明式导航 */}
      <div>
        <NavLink end to="/home" state={
    
    {
    
     id: 1000 }}>首页</NavLink>
        <span> --- </span>
        <NavLink to="/about">关于</NavLink>
        <span> --- </span>
        <NavLink to="/admin">后台</NavLink>
      </div>
      <hr />
      <Routes>
        {
    
    /* 嵌套路由,就是把定义规则的Route由单标签更换成双标签就可以,里面还是要定义规则 */}
        <Route path="/admin" element={
    
    <Admin />}>
          {
    
    /* 嵌套路由 之 默认页 */}
          <Route index element={
    
    <Welcome />} />

          {
    
    /* path中开头不要写 / 就可以 ,它会自动把父组件中的path拼接过来 /admin/welcome */}
          {
    
    /* 非默认页,需要点击导航跳转 */}
          {
    
    /* <Route path="welcome" element={<Welcome />} /> */}
          {
    
    /* 重定向到欢迎页,重定向生效需要上一句代码 */}
          {
    
    /* <Route index element={<Navigate to="/admin/welcome" replace />} /> */}

          <Route path="user" element={
    
    <User />} />
        </Route>


        <Route path='/home' element={
    
    <Home />} />
        <Route path='/about' element={
    
    <About />} />
        {
    
    /* 动态路由参数定义 */}
        <Route path="/detail/:id" element={
    
    <Detail />} />
        {
    
    /* 重定向 */}
        {
    
    /* Navigate重定向  to跳转到url地址  replace是否可以回退 */}
        <Route path="/" element={
    
    <Navigate to="/home" replace={
    
    false} />} />
        {
    
    /* 404页面处理 */}
        <Route path="*" element={
    
    <div>没有页面</div>} />
      </Routes>
    </div>
  )
}

export default App

后台首页组件:

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

const Admin = () => {
    
    
  return (
    <div>
      <h3>后台管理</h3>
      <div>
        {
    
    /* 没有默认页 */}
        {
    
    /* <NavLink to="/admin/welcome">首页</NavLink> */}
        {
    
    /* 显示默认页 */}
        <NavLink to="/admin">首页</NavLink>
        <span> -- </span>
        <NavLink to="/admin/user">用户</NavLink>
      </div>
      <hr />
      {
    
    /* Admin组件它是一个父路由渲染的组件,它里面有嵌套路由,需要一个占位 */}
      <Outlet />
    </div>
  )
}

export default Admin

请添加图片描述

7. useRoutes实现配置式路由

router/index.js:

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

import Home from '../views/Home'
import About from '../views/About'
import Detail from '../views/Detail'
import Admin from '../views/Admin'
import Welcome from '../views/Welcome'
import User from '../views/User'

export default [
  {
    
     path: '/', element: <Navigate to="/home" replace /> },
  {
    
    
    path: '/home',
    element: <Home />
  },
  {
    
    
    path: '/about',
    element: <About />
  },
  {
    
    
    path: '/detail/:id',
    element: <Detail />
  },
  {
    
    
    path: '/admin',
    element: <Admin />,
    children: [
      {
    
     index: true, element: <Navigate to="/admin/welcome" replace /> },
      {
    
    
        path: 'welcome',
        element: <Welcome />
      },
      {
    
    
        path: 'user',
        element: <User />
      }
    ]
  }
]

父组件:

import React from 'react'
import {
    
     NavLink, useRoutes } from 'react-router-dom'
import routes from './router'

const App = () => {
    
    
  const routeElement = useRoutes(routes)

  return (
    <div>
      <div>
        <NavLink to="/home">首页</NavLink>
        <span> --- </span>
        <NavLink to="/about">关于</NavLink>
        <span> --- </span>
        <NavLink to="/admin">后台</NavLink>
      </div>
      <hr />
      {
    
    routeElement}
    </div>
  )
}

export default App

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45605541/article/details/127354810