React学习06-React Router 6

news2024/11/17 10:02:25

React Router 6 概述

  1. React Router 以三个不同的包发布到 npm 上,它们分别为:

    1. react-router: 路由的核心库,提供了很多的:组件、钩子。
    2. react-router-dom: 包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如 <BrowserRouter>等。
    3. react-router-native: 包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:<NativeRouter>等。
  2. 与React Router 5.x 版本相比,改变了什么?

    1. 内置组件的变化:移除<Switch/> ,新增 <Routes/>等。
    2. 语法的变化:component={About} 变为 element={<About/>}等。
    3. 新增多个hook:useParamsuseNavigateuseMatch等。
    4. 官方明确推荐函数式组件了!!!

准备工作

创建新项目:

npx create-react-app router6

目前create-react-app默认创建为React 18,先降到17版本:

npm install react@17.x react-dom@17.x --save

安装react-router-dom

npm i react-router-dom

若以上命令出现报错,则加后缀:--legacy-peer-deps

编写基本内容:

  1. 项目结构
    image.png

  2. index.js

    import React from "react"
    import ReactDOM from "react-dom"
    import { BrowserRouter } from "react-router-dom"
    import App from "./App"
    
    ReactDOM.render(
        <BrowserRouter>
            <App />
        </BrowserRouter>,
        document.getElementById('root')
    )
    

    App.jsx声明函数式组件

一级路由

React Router 6中,<Route />component属性已替换为elementSwitch已弃用并替换为Routes,值得注意的是,在React Router 5中,用<Switch></Switch>包裹<Route />不是必须的,但在React Router 6中必须用<Routes></Routes>包裹<Route />

App.jsx

import React from 'react'
import { NavLink, Routes, Route } from 'react-router-dom'
import About from './pages/About'
import Home from './pages/Home'

export default function App() {
    return (
        <div>
            <div className="row">
                <div className="col-xs-offset-2 col-xs-8">
                    <div className="page-header"><h2>React Router Demo</h2></div>
                </div>
            </div>
            <div className="row">
                <div className="col-xs-2 col-xs-offset-2">
                    <div className="list-group">
                        {/* 路由链接 */}
                        <NavLink className="list-group-item" to="/about">About</NavLink>
                        <NavLink className="list-group-item" to="/home">Home</NavLink>
                    </div>
                </div>
                <div className="col-xs-6">
                    <div className="panel">
                        <div className="panel-body">
                            {/* 注册路由 */}
                            <Routes>
                                <Route path='/about' element={<About/>} />
                                <Route path='/home' element={<Home/>} />
                            </Routes>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

GIF 2022-5-21 19-03-58.gif

重定向

React Router 6已将原有的Redirect删除,现在使用Navigate

只要<Navigate />组件被渲染,就会修改路径、切换视图

  • to属性:重定向地址
  • replace属性:false为push,true为replace

使用:嵌套在Route标签中使用

<Route path='/' element={<Navigate to='/about' />} />

需求:点击使sum+1并实现路由跳转

import React, {useState} from 'react'
import { Navigate } from 'react-router-dom'

export default function Home() {
  const [sum, setSum] = useState(1)
  return (
    <>
      <h3>我是Home的内容</h3>
      {sum === 2 ? <Navigate to="/about" /> : <h4>当前sum的值是:{sum}</h4>}
      <button onClick={() => setSum(2)}>点击sum+1</button>
    </>
  )
}

GIF 2022-5-24 19-52-53.gif

NavLink

作用: 与<Link>组件类似,且可实现导航的“高亮”效果,与Router 5不同的是,不在使用activeClassName,而是如下所示:

<NavLink
    to="login"
    className={({ isActive }) => {
        console.log('home', isActive)
        return isActive ? 'base one' : 'base'
    }}
>login</NavLink>

默认情况下,当Home的子组件匹配成功,Home的导航也会高亮,当NavLink上添加了end属性后,若Home的子组件匹配成功,则Home的导航没有高亮效果。

路由表

使用useRoutes Hook,根据路由表,动态创建<Routes><Route>

import React from 'react'
import { NavLink, Navigate, useRoutes } from 'react-router-dom'
import About from './pages/About'
import Home from './pages/Home'

export default function App() {
    // 根据路由表生成对应的路由规则
    const element = useRoutes([
        {
            path: '/about',
            element: <About/>
        },
        {
            path: '/home',
            element: <Home/>
        },
        {
            path: '/',
            element: <Navigate to="/about"/>
        }
    ])

    return (
        <div>
            <div className="row">
                <div className="col-xs-offset-2 col-xs-8">
                    <div className="page-header"><h2>React Router Demo</h2></div>
                </div>
            </div>
            <div className="row">
                <div className="col-xs-2 col-xs-offset-2">
                    <div className="list-group">
                        {/* 路由链接 */}
                        <NavLink className="list-group-item" to="/about">About</NavLink>
                        <NavLink className="list-group-item" to="/home">Home</NavLink>
                    </div>
                </div>
                <div className="col-xs-6">
                    <div className="panel">
                        <div className="panel-body">
                            {/* 注册路由 */}
                            {element}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

嵌套路由

路由表写法:

/* eslint-disable import/no-anonymous-default-export */
import { Navigate } from "react-router-dom"
import About from "../pages/About"
import Home from "../pages/Home"
import Message from "../pages/Message"
import News from "../pages/News"

export default [
    {
        path: '/about',
        element: <About />
    },
    {
        path: '/home',
        element: <Home />,
        children: [
            {
                path: 'message', // 不要有斜线
                element: <Message />
            },
            {
                path: 'news',
                element: <News />
            },
        ]
    },
    {
        path: '/',
        element: <Navigate to="/about" />
    }
]

Home组件:使用<Outlet />,当<Route>产生嵌套时,渲染其对应的后续子路由。

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

export default function Home() {
  return (
    <div>
      <h2>Home组件内容</h2>
      <div>
        <ul className="nav nav-tabs">
          <li>
            <NavLink className="list-group-item" to="news">News</NavLink> {/* 不能写斜线 */}
          </li>
          <li>
            <NavLink className="list-group-item" to="message">Message</NavLink>
          </li>
        </ul>
        {/* 指定路由组件呈现的位置 */}
        <Outlet />
      </div>
    </div>
  )
}

传递参数

params参数

  1. 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>

  2. 在路由表中声明接收参数:

    path: 'message', // 不要有斜线
    element: <Message />,
    children: [
        {
            path: 'detail/:id/:title/:content',
            element: <Detail />
        }
    ]
    
  3. 接收参数:const {id, title, content} = useParams()

Message组件:

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

export default function Message() {

    const [messages] = useState([
        {id: '001', title: 'message1', content: 'abcdefg'},
        {id: '002', title: 'message2', content: 'hijklmn'},
        {id: '003', title: 'message3', content: 'opqrst'},
        {id: '004', title: 'message4', content: 'uvwxyz'},
    ])

    return (
        <div>
            <ul>    
                {
                    messages.map((message) => {
                        return (
                            <li key={message.id}>
                                <Link to={`detail/${message.id}/${message.title}/${message.content}`}>{message.title}</Link>&nbsp;&nbsp; 
                            </li>
                        )
                    })
                }
            </ul>
            <hr />
            {/* 指定路由组件的展示位置 */}
            <Outlet />
        </div>
    )
}

Detail组件:

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

export default function Detail() {
  const {id, title, content} = useParams()
  const x = useMatch('/home/message/detail/:id/:title/:content')
  console.log(x)
  return (
    <ul>
        <li>id: {id}</li>
        <li>title: {title}</li>
        <li>content: {content}</li>
    </ul>
  )
}

search参数

  1. 路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link>
  2. 注册路由(无需声明,在路由表中正常注册即可)
  3. 接收参数:const [search, setSearch] = useSearchParams()

Detail组件:

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

export default function Detail() {
  const [search, setSearch] = useSearchParams()
  const id = search.get('id')
  const title = search.get('title')
  const content = search.get('content')
  const x = useLocation()
  console.log(x)
  return (
    <ul>
        <li>
            <button onClick={() => setSearch('id=005&title=阿巴阿巴&content=ohhhhhh')}>点击修改search参数</button>
        </li>
        <li>id: {id}</li>
        <li>title: {title}</li>
        <li>content: {content}</li>
    </ul>
  )
}

GIF 2022-5-27 22-23-06.gif

state参数

传递的内容不会在地址栏展示,与组件的状态(state)不同

  1. 路由链接(携带参数):

    <Link
        to='detail'
        state={{
            id: message.id,
            title: message.title,
            content: message.content
        }}>{message.title}
    </Link>
    
  2. 注册路由(无需声明,在路由表中正常注册即可)

  3. 接收参数:const {state: {id, title, content}} = useLocation()

  4. 备注:刷新也可以保留住参数,但清除浏览器数据后不可

编程式路由导航

需求:鼠标滑过时引起组件渲染,这时<Link/> <NavLink/> <Navigate/>都不能胜任

import React, { useState } from 'react'
import { Link, Outlet, useNavigate } from 'react-router-dom'

export default function Message() {

    const [messages] = useState([
        {id: '001', title: 'message1', content: 'abcdefg'},
        {id: '002', title: 'message2', content: 'hijklmn'},
        {id: '003', title: 'message3', content: 'opqrst'},
        {id: '004', title: 'message4', content: 'uvwxyz'},
    ])

    const navigate = useNavigate()

    function show(message) {
        navigate('detail', {
            replace: false, // 默认为false,可不写
            state: {
                id: message.id,
                title: message.title,
                content: message.content
            }
        })
    }

    return (
        <div>
            <ul>    
                {
                    messages.map((message) => {
                        return (
                            <li key={message.id}>
                                <Link
                                    to='detail'
                                    state={{
                                        id: message.id,
                                        title: message.title,
                                        content: message.content
                                    }}>{message.title}
                                </Link>&nbsp;&nbsp; 
                                <button onClick={() => show(message)}>展示详情</button>
                            </li>
                        )
                    })
                }
            </ul>
            <hr />
            {/* 指定路由组件的展示位置 */}
            <Outlet />
        </div>
    )
}

GIF 2022-5-27 22-54-09.gif

扩展:前进与后退

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

export default function Header() {
    const navigate = useNavigate()
    function back() {
        navigate(-1)
    }
    function forward() {
        navigate(1)
    }
    return (
        <div className="col-xs-offset-2 col-xs-8">
            <div className="page-header">
                <h2>React Router Demo</h2>
                <button onClick={back}>👈后退</button>
                <button onClick={forward}>前进👉</button>
            </div>
        </div>
    )
}

其他的Hooks

useInRouterContext()

主要用于判断当前组件(一般组件和路由组件)是否处于路由的上下文环境中,即组件被BrowserRouterHashRouter包裹(包括子组件),不在路由的上下文环境中,即脱离了路由器的管理

返回一个布尔值,处于路由的上下文环境中时返回真。

useNavigationType()

返回当前的导航类型

  • POP:在浏览器中直接打开或刷新页面
  • PUSH
  • REPLACE

useOutlet()

用来呈现当前组件中渲染的嵌套路由

  • console.log(useOutlet())
  • 如果嵌套路由没有挂载,则输出null
  • 如果嵌套路由已经挂载,则展示嵌套的路由对象

useResolvedPath()

给定一个URL值,解析其中的pathsearchhash

console.log(useResolvedPath('/user?id=01&name=abc&se=hi#goto'))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch处理表关联关系的N种方式

Elasticsearch处理表关联关系是比较复杂的问题&#xff0c;处理不好会出现性能问题、数据一致性问题等&#xff1b; 今天我们特意分享一下几种方式&#xff0c;对象类型&#xff08;宽表&#xff09;、嵌套类型、父子关联关系、应用端关联&#xff0c;每种方式都有特定的业务需…

CycloneDDS(3)安全Security

本规范定义了符合DDS实现的安全模型和服务插件接口(SPI)架构。DDS安全模型通过DDS实现调用这些SPI来实现。 构成DDS安全模型的三个插件是: 1、身份验证服务插件 提供验证调用DDS操作的应用程序和/或用户身份的方法。包括在参与者之间执行相互身份验证和建立共享秘密的设施…

深度学习模型训练的tricks总结

学习率角度 学习率是一个非常非常重要的超参数&#xff0c;这个参数呢&#xff0c;面对不同规模、不同batch-size、不同优化方式、不同数据集&#xff0c;其最合适的值都是不确定的&#xff0c;我们无法光凭经验来准确地确定lr的值&#xff0c;我们唯一可以做的&#xff0c;就…

从零开始配置vim(30)——DAP的其他配置

很抱歉这么久才来更新这一系列&#xff0c;主要是来新公司还在试用期&#xff0c;我希望在试用期干出点事来&#xff0c;所以摸鱼的时间就少了。加上前面自己阳了休息了一段时间。在想起来更新就过去一个多月了。废话不多说了&#xff0c;让我们开始进入正题。 在前一章&#…

JUC 并发进阶学习(一)

该学习笔记是本人依据相关的学习视频整体汇总&#xff0c;相关的视频学习可以自己去搜看看。 【狂神说Java】JUC并发编程最新版通俗易懂_哔哩哔哩_bilibili 一、什么是JUC 从中就可以看出JUC&#xff0c;实质就是三个包&#xff0c;后面晖详细说明三个包下各个类功能。 java.…

程序员的测试课

git项目地址&#xff1a;GitHub - dreamhead/geektime-todo: Geektime Todo is a demo todo project for Geektime column. 1、实现一个Todo应用 设计规范 1、对于输入参数的检测&#xff0c;由入口部分代码进行处理。如空字符串。 2、Repository 的问题以运行时异常 的形式抛…

Django+Celery+Flower实现异步和定时任务及其监控告警

用Django框架进行web开发非常的快捷方便&#xff0c;但Django框架请求/响应是同步的。但我们在实际项目中经常会碰到一些耗时的不能立即返回请求结果任务如&#xff1a;数据爬取、发邮件等&#xff0c;如果常时间等待对用户体验不是很好&#xff0c;在这种情况下就需要实现异步…

SOFA Weekly|2023 我们一起加油、本周 Contributor QA

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…

RocketMQ 搭建

目录 1、什么是MQ&#xff1f;为什么要用MQ&#xff1f; 2、MQ的优缺点 3、几大MQ产品特点比较 4.RocketMQ在Windows的启动 1.下载RocketMQ 4.7.1版本 2.解压到本地磁盘并配置好JAVA_HOME和ROCKETMQ_HOME 3.修改runserver.cmd 4.启动server 5.修改runbroker.cmd 6.启动…

ROS2 基础概念 服务

ROS2 基础概念 服务1. Services2. 服务类型3. 查找服务4. 服务请求1. Services 服务基于 请求-应答 模型&#xff0c;而不是话题的 发布-订阅 模型 虽然话题允许节点订阅数据流并获得持续更新&#xff0c;但服务 仅在客户端专门调用时提供数据 还是启动海龟及其遥控节点为例&…

[标准库]STM32F103R8T6 点灯以及按键扫描

刚开始学32的时候&#xff0c;选择了基于HAL库进行开发&#xff0c;原因是HAL比较容易上手&#xff0c;像点灯、输出PWM、按键输入这种操作都很快捷。但是到ADCDMA这部分的时候发现&#xff0c;HAL库有一些地方我认为不是很合理和方便。比如DMA中断这部分&#xff0c;ST官方给出…

音视频开发系列--H264编解码总结

一、概述 H264&#xff0c;通常也被称之为H264/AVC&#xff08;或者H.264/MPEG-4 AVC或MPEG-4/H.264 AVC&#xff09; 对摄像头采集的每一帧视频需要进行编码&#xff0c;由于视频中存在空间和时间的冗余&#xff0c;需要用算法来去除这些冗余。H264是专门去除这些冗余的算法…

王者荣耀崩溃解决记录

王者荣耀竟然崩溃了 上周玩王者荣耀&#xff0c;突然就进不去了&#xff0c;点击开始游戏后应用直接就崩溃退出了。 第一反应&#xff0c;肯定是反馈给游戏客服。但是果然腾讯的游戏是找不到真客服的&#xff0c;全部都是机器人处理的&#xff0c;给了我一个毫无用处的官方回…

springboot中配置文件优先级以及分类,这你都可以不会吗?不会赶紧进来学( ̄(∞) ̄)

各位小伙伴大家好呀┗( ▔, ▔ )┛&#xff0c;马上过年了&#xff0c;但是感觉没啥期待的哈哈哈哈哈&#xff0c;现在的年说实话真的挺没劲的呜呜。 言归正传&#xff0c;我们大家在使用springboot时难免会写各种各样的配置信息&#xff0c;比如port&#xff0c;jdbc啊这些&am…

2022这一年:阳了、变轨和逆风

又到年末了&#xff0c;2022这一年应该会让人记忆深刻&#xff0c;于我而言这一年的感受有明显的分界线&#xff0c;在此之前的世界温暖一些&#xff0c;提供着能量&#xff0c;让人心生探索它的纷繁多彩&#xff1b;今年世界变得寒冷了&#xff0c;展示着它的严酷与无情。阳了…

再学C语言20:循环控制语句——for循环

在while循环中&#xff0c;建立一个重复执行固定次数的循环涉及到3个动作&#xff1a; 1&#xff09;初始化一个计数器 2&#xff09;计数器与某个有限的值比较 3&#xff09;每次执行循环&#xff0c;要在循环体中让计数器的值递增 其中&#xff0c;计数器的初始化在循环之…

【pandas】教程:6-如何计算摘要统计

Pandas 计算摘要统计 本节使用的数据为 data/titanic.csv&#xff0c;链接为 pandas案例和教程所使用的数据-机器学习文档类资源-CSDN文库 加载数据 import pandas as pdtitanic pd.read_csv("data/titanic.csv") titanic.head()PassengerId Survived Pclass \…

#Z0424. 树上的旅行

题目 Description 给出一棵有N个结点的树&#xff0c;给出Q个询问&#xff0c;求结点xj过结点K到节点yj的最短距离 Format Input 第一行一个数n 接下来共有n-1行&#xff0c;三个数u,v,len表示u和v之间存在一条边长为len 再给你Q&#xff0c;K。代表有Q个询问&#xff0…

视频 | bedtools使用介绍1

点击阅读原文跳转完整教案。基因组中的趣事&#xff08;二&#xff09;- 最长的基因2.7 million&#xff0c;最短的基因只有8 nt却能编码基因组中的趣事&#xff08;一&#xff09;&#xff1a;这个基因编码98种转录本1 Linux初探&#xff0c;打开新世界的大门1.1 Linux系统简介…

10000+条数据的内容滚动功能如何实现?

遇到脑子有问题的产品经理该怎么办&#xff1f;如果有这么一个需求要你在一个可视区范围内不间断循环滚动几千上万条数据你会怎么去实现&#xff1f; 且不说提这个需求的人是不是脑子有问题&#xff0c;这个需求能不能实现&#xff1f;肯定是可以的&#xff0c;把数据请求回来渲…