React07-路由管理器react-router-dom(v6)

react-router 是一个流行的用于 React 应用程序路由的库。它使我们能够轻松定义应用程序的路由,并将它们映射到特定的组件,这样可以很容易地创建复杂的单页面应用,并管理应用程序的不同视图。

react-router 是基于 React 构建的,因此与其他 React 库和工具集成得很好。它在许多 React 应用程序中广泛使用,并被认为是 React 中最佳实践的路由。

一、react-router-dom安装和简介

1. react-router-dom安装

使用 npm 或 yarn 安装 react-router-dom。

npm install --save react-router-dom

yarn add react-router-dom

2. react-router-dom 简介

react-router-dom 是 react-router 的一种实现方案,主要应用于网页端应用,它提供了一些常用的组件进行路由管理。

(1) Router 类组件

  • BrowserRouter:history 模式下的路由。
  • HashRouter:hash 模式下的路由。

(2) Route 组件

Route 是一个路由配置组件。

(3) Link 组件

Link 类似于 a 标签,可以用于路由跳转。

(4) useNavigate Hook

useNavigate 是一个钩子函数,可以用于路由跳转。

二、react-router-dom 基本使用

1. 引入 react-router-dom

import {BrowserRouter as Router, Routes, Route} from 'react-router-dom';

这里的 BrowserRouter as Router 相当于给 BrowserRouter 起了一个别名叫 Router。Routes 组件用于包裹 Route 组件,Route 组件的父组件必须是 Routes。

2. 简单使用

使用 BrowserRouter 组件包裹 Routes 组件,再用 Routes 组件包裹 Route 组件,在 Route 组件中定义路由信息,就实现了一个简单的 react-router 场景。

Route 组件有 path 和 element 两个属性,path 属性代表路由路径,element 属性代表要渲染的组件。

index.js

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>
);

app.js

import './App.css';
import { Routes, Route} from "react-router-dom";
import Home from "./views/Home";
import About from "./views/About";
import Error from "./views/Error";function App() {return (<div className="App"><Routes><Route path="/" element={<Home/>}/><Route path="/about" element={<About/>}/><Route path="*" element={<Error/>}/></Routes></div>);
}export default App;

在上面的案例中,我们定义了一个根路由,指向 Home 页面。还定义一个指定路径路由 /about,指向 About 页面,表示当我们在浏览器地址栏中的页面地址后加上 /about 时,会跳转到 About 页面。

又定义了一个通用路由,指向 Error 页面,path="*" 表示如果浏览器地址栏中的页面地址不是以上定义的2种路由(即其他路由地址)时,就会跳转到 Error 页面。

注意:BrowserRouter 组件最好放在最顶层所有组件之外,这样能确保内部组件使用 Link 做路由跳转时不出错。

3. 路由跳转

跳转路由时,如果路由路径是 / 开头的是绝对路由,否则是相对路由,即相对于当前 URL进行改变。

(1) Link 组件

Link 组件只能在 Router 组件的内部使用,to 属性代表要跳转的路由地址。

import { Link } from "react-router-dom";
<Link to="/about">To About</Link>

(2) NavLink 组件

NavLink 组件和 Link 组件的功能是一致的,区别在于 NavLink 组件可以判断其 to 属性是否是当前匹配到的路由。
NavLink组件的 style 属性或 className 属性可以接收一个函数,函数接收一个含有 isActive 字段的对象为参数,可根据该参数调整样式。

import { Link } from "react-router-dom";
<NavLink to="/about" style={({ isActive }) => ( {color: isActive ? "red" : "black"} )}>To About</NavLink>

(3) useNavigate Hook

使用 useNavigate 钩子函数,可以在 js 代码中实现路由跳转。

useNavigate 必须在 Route 的上下文中使用,即必须包裹在 Router 标签内。

import { useNavigate } from "react-router-dom";
<button onClick={() => navigate("/about")}>To About</button>

4. 路由参数

(1) 路径参数(动态路由匹配)

在 Routes 组件内定义路由。对于动态路由,使用冒号(:)来指定动态部分。例如,要定义一个动态用户路由,可以:

App.js

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

这里的 :userId 是动态部分,可以匹配任何放在 /user/ 后面的路径,比如 /user/123。

在路由的目标组件中,可以使用 useParams 钩子来访问动态参数。例如,在 User 组件中,可以这样获取 userId:

User.js

mport { useParams } from 'react-router-dom';function User {let { userId } = useParams();console.log(userId); // 123// 使用 userId 作为你的逻辑的一部分
}export default User;

上述案例中,访问 /user/123 能正确获取到 userId 为123。

(2) 查询参数

查询参数不需要在路由中定义,可以使用 useSearchParams 钩子函数来处理路径中的查询参数。

查询参数位于 URL 中,用于提供额外信息以便服务器能够更具体地处理请求。它们通常出现在网页地址(URL)的末尾,并且遵循一定的格式。

在 URL 中,查询参数是通过问号(?)与网址的其它部分分隔开的,并且可以包含一个或多个键值对。每个键值对都由一个键(key)和一个值(value)组成,用等号(=)连接。如果有多个查询参数,它们之间通常用符号与(&)分隔。

例如,在 URL https://example.com/page?param1=value1&param2=value2 中, param1=value1 和 param2=value2 是查询参数,它们提供了额外的信息给服务器。

useSearchParams Hook 返回当前组件获取到的查询参数对象及修改这个对象的方法,使用方法和 useState Hook 类似。

在使用 setSearchParams 方法时,必须传入所有查询参数,否则会覆盖已有查询参数。

import { useSearchParams } from 'react-router-dom';function User() {// 使用 useSearchParams 钩子const [searchParams, setSearchParams] = useSearchParams();// 获取查询参数const userId = searchParams.get('userId');// 设置查询参数const setUserId = (newUserId) => {setSearchParams({ userId: newUserId });};// 渲染组件return (<div><p>当前的 userId 是:{userId}</p><button onClick={() => setUserId('123')}>设置 userId 为 123</button></div>);
}export default User;

上述案例中,访问 /user?userId=123456 时,效果如下:

点击按钮后,userId 变为 123,符合预期。

(3) 状态参数

react-router 对 window.location 进行了包装,状态参数就位于包装后的 location 对象的 state 属性中。下面为包装后的 location 对象的属性:

react-router包装后的location对象
pathname主机名之后的 URL 地址
search查询参数
hash哈希值,用于确定页面滚动的具体位置
state对于 window.history.state 的包装
key每个 location 对象拥有一个唯一的 key

state 不显示在页面上,不会引起页面刷新,可用于记录用户的跳转详情或在跳转时携带信息,可以用在 Link 组件或 navigate 方法中使用状态参数。

{/* Link 中使用状态参数 */}
<Link to="/about" state={{ id: 123 }} >To About</Link>{/* useNavigate 中使用状态参数 */}
<button onClick={() => navigate("/about", { state: { id: 456 } })}>To About</button>

在目标组件中,使用 useLocation 来获取封装后的 loaction 对象,进而获取状态参数。

const location = useLocation();
console.log(location.state);

5. 路由重定向

当在某个路径 /a ,要重定向到路径 /b 时,可以通过 Navigate 组件进行重定向到其他路径。

import { Navigate } from “react-router-dom”;function A() {return <Navigate to=”/b" />;
}export default A;

三、react-router-dom 进阶使用

1. 嵌套路由

嵌套路由是前端开发中用于组织和管理路由的一种技术,特别适用于构建具有层次结构的页面和应用程序。

在 Route 组件内定义 Route 组件实现嵌套路由,在父组件中使用 Outlet 组件作为子组件的占位符(显示匹配到的子组件)。

在嵌套路由中,如果 URL 仅匹配了父级 URL,则 Outlet 组件中会显示带有 index 属性的子路由,这个子路由称为默认路由。

例3-1:根据用户 id 显示用户详细信息

App.js

import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
import Home from './views/Home';
import Users from './views/Users';
import UserList from "./views/UserList";
import UserDetail from "./views/UserDetail";function App() {return (<Router><nav><Link to="/">Home</Link> |<Link to="/users">User</Link></nav><Routes><Route path="/" element={<Home />} /><Route path="users" element={<Users />}><Route index element={<UserList />} /><Route path=":userId" element={<UserDetail />} /></Route></Routes></Router>);
}export default App;

Users.js

import { Link, Outlet } from "react-router-dom";function Users() {return (<div><h2>Users</h2><nav><Link to="list">User List</Link></nav><Outlet /></div>);
}export default Users;

UserList.js

import { Link } from "react-router-dom";function UserList() {const users = [{id: "1", name: 'John'},{id: "2", name: 'Jane'},{id: "3", name: 'Mary'},];return (<div><h2>User List</h2><ul>{users.map((user) => (<li key={user.id}><Link to={`/users/${user.id}`}>{user.name}</Link></li>))}</ul></div>);
}export default UserList;

UserDetail.js

import { useParams } from 'react-router-dom';function UserDetail() {const { userId } = useParams();const users = [{id: "1", name: 'John'},{id: "2", name: 'Jane'},{id: "3", name: 'Mary'},];return (<div><h3>User Detail</h3><h3>id:{userId}</h3><h3>name:{users.find((user) => user.id === userId).name}</h3></div>)
}export default UserDetail;

上述案例中,在根组件 App 中定义了一组嵌套路由,一级路由为 / 和 users。又在 users 中嵌套了默认路由和动态路由 :userid。

在这个嵌套路由中,Users 组件为父组件,UserList 和 UserDetail 组件为子组件。在 Users 组件中使用了 Outlet 组件,作为匹配到的子组件的占位符。可以使用在路由的任何层级。当访问 /users 时,这里触发默认路由显示 UserList 组件。当访问 /users/2 时,会显示 UserDetail 组件。

访问 /users:

访问 /users/2:

2. 多组路由

多组路由指的是在单个应用中设置多个独立的路由组,可以在不同部分的应用中实现独立的路由逻辑,增加了路由结构的灵活性和模块化。

在 react-router-dom 中,可以通过在不同的组件中定义多个 Routes 组件来实现多组路由。

例3-2 管理系统案例

App.js

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import MainSite from './views/MainSite';
import AdminPanel from './views/AdminPanel';function App() {return (<Router><Routes><Route path="*" element={<MainSite />} /><Route path="admin/*" element={<AdminPanel />} /></Routes></Router>);
}export default App;

MainSite.js

import { Routes, Route, Link } from 'react-router-dom';
import Home from './Home';
import About from './About';function MainSite() {return (<div><nav><Link to="/">Home</Link> |<Link to="/about">About</Link></nav><Routes><Route path="/" element={<Home />} /><Route path="about" element={<About />} /></Routes></div>);
}export default MainSite;

AdminPanel.js

import { Routes, Route, Link } from 'react-router-dom';
import Dashboard from './Dashboard';
import Users from './Users';function AdminPanel() {return (<div><nav><Link to="/admin/dashboard">Dashboard</Link> |<Link to="/admin/users">Users</Link></nav><Routes><Route path="dashboard" element={<Dashboard />} /><Route path="users" element={<Users />} /></Routes></div>);
}export default AdminPanel;

上述案例构建了一个具有两个独立路由组的应用,这两个路由组分别是主站(MainSite 组件)和管理面板(AdminPanel 组件)。MainSite 组件包含了应用的主要页面,如首页(Home)和关于页面(About);AdminPanel 组件是应用的管理面板,包含了仪表盘(Dashboard)和用户管理(Users) 界面。

App.js 中定义了应用的顶级路由结构,使用 Routes 来定义两个主要路由路径:* 和 /admin/*。每个路径指向对应的 MainSite 和 AdminPanel 组件。* 路径指向 MainSite 组件,该组件处理与主站相关的子路由。/admin/* 路径指向 AdminPanel 组件,该组件处理与管理面板相关的子路由。

当访问 / 时,展示 MainSite 组件和 Home 组件;访问 /about,展示 MainSite 组件和 About 组件;访问 /admin,展示 AdminPanel 组件;访问 /admin/dashboard,展示 AdminPanel 组件和 Dashboard 组件。

3. 布局路由

布局路由是一种组织和管理路由的方式,它允许开发者将路由与其对应的布局分开管理。这在复杂的应用中特别有用,因为它可以帮助保持代码的清晰和模块化。

布局路由是指一种模式,其中一组路由共享相同的布局组件。这意味着这些路由的所有页面都将有相同的外观和感觉,例如共享的头部和底部导航栏。布局组件负责渲染这些共享元素,而特定的子路由则负责渲染页面的主要内容。

例3-3 升级版管理系统案例

App.js

同案例3-2。

MainSite.js

import React from 'react';
import {Routes, Route, Link} from 'react-router-dom';
import Home from './Home';
import About from './About';
import Header from './Header';
import Footer from './Footer';
import Error from "./Error";function MainSite() {return (<div><Header /><nav><Link to="/">Home</Link> |<Link to="/about">About</Link></nav><Routes><Route index element={<Home />} /><Route path="about" element={<About />} />{/* 更多主站的路由可以在这里添加 */}{/* 捕获所有未匹配的路由并显示 Error 组件 */}<Route path="*" element={<Error />} /></Routes><Footer /></div>);
}export default MainSite;

AdminPanel.js

import React from 'react';
import {Routes, Route, Link} from 'react-router-dom';
import Dashboard from './Dashboard';
import Users from "./Users";
import AdminHeader from './AdminHeader';
import AdminFooter from './AdminFooter';
import Error from "./Error";function AdminPanel() {return (<div><AdminHeader /><nav><Link to="/admin">Dashboard</Link> |<Link to="/admin/users">Users</Link></nav><Routes><Route path="" element={<Dashboard />} /><Route path="users" element={<Users />} />{/* 更多管理面板的路由可以在这里添加 */}{/* 捕获所有未匹配的路由并显示 Error 组件 */}<Route path="*" element={<Error />} /></Routes><AdminFooter /></div>);
}export default AdminPanel;

上述案例中,我们在 MainSite 和 AdminPanel 中加入了 Header 和 Footer 布局组件,同时添加了一个用于处理所有未匹配路由的 Error 组件。

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

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

相关文章

大模型PEFT技术原理(一):BitFit、Prefix Tuning、Prompt Tuning

随着预训练模型的参数越来越大&#xff0c;尤其是175B参数大小的GPT3发布以来&#xff0c;让很多中小公司和个人研究员对于大模型的全量微调望而却步&#xff0c;近年来研究者们提出了各种各样的参数高效迁移学习方法&#xff08;Parameter-efficient Transfer Learning&#x…

【开源】基于JAVA的婚恋交友网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 会员管理模块2.3 新闻管理模块2.4 相亲大会管理模块2.5 留言管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 会员信息表3.2.2 新闻表3.2.3 相亲大会表3.2.4 留言表 四、系统展示五、核心代码5.…

lvs+keepalived+nginx双主模式双主热备实现负载均衡

目录 一、原理 二、真实服务器nginx配置 三、lvs的keepalived配置 3.1 配置文件 3.2 开启keepalived服务 四、测试 4.1 测试访问VIP 4.2 模拟lvs01宕机 主机名IPnginx0111.0.1.31nginx0111.0.1.31lvs0111.0.1.33lvs0211.0.1.34VIP111.0.1.29VIP211.0.1.30 一、原理 lvskeepal…

OpenAI推出GPT商店和ChatGPT Team服务

&#x1f989; AI新闻 &#x1f680; OpenAI推出GPT商店和ChatGPT Team服务 摘要&#xff1a;OpenAI正式推出了其GPT商店和ChatGPT Team服务。用户已经创建了超过300万个ChatGPT自定义版本&#xff0c;并分享给其他人使用。GPT商店集结了用户为各种任务创建的定制化ChatGPT&a…

windows10 装docker和docker compose

一.windows环境准备 开启过程中的问题&#xff0c;进入bios修复 二.docker下载安装 1.下载 Docker Desktop: The #1 Containerization Tool for Developers | Docker 下载最新版有问题&#xff0c;下载老版本试试 Docker Desktop release notes | Docker Docs 2.安装 三.do…

系统存储架构升级分享

一、业务背景 系统业务功能&#xff1a;系统内部进行数据处理及整合, 对外部系统提供结果数据的初始化(写)及查询数据结果服务。 系统网络架构: • 部署架构对切量上线的影响 - 内部管理系统上线对其他系统的读业务无影响 •分布式缓存可进行单独扩容, 与存储及查询功能升级…

出版实务 | 出版物的成本及其构成

文章目录 出版物成本的总体构成直接成本开发成本制作成本 间接成本期间费用 本量利分析原则特点和作用变动成本项目固定成本项目本量利分析的基本公式及其应用定价发行折扣率销售数量单位销售收入销售收入总额单位销售税金销售税金总额变动成本总额单位变动成本固定成本总额单位…

CMake入门教程【高级篇】CPack打包项目Linux的deb和windows的msi

😈「CSDN主页」:传送门 😈「Bilibil首页」:传送门 😈「动动你的小手」:点赞👍收藏⭐️评论📝 文章目录 1. 什么是CPack?2. 如何使用CPack?2.1 在CMakeLists.txt中包含CPack模块2.2 设置CPack变量2.3 创建分发包3.CPack命

转专业(UPC练习)

题目描述 根据教育部的规定&#xff0c;大学生进校后符合条件的可申请转专业。在校本科生在完成大学一年级课程&#xff0c;进入二年级之前&#xff0c;符合以下条件之一者&#xff0c;可以申请转专业&#xff1a;&#xff08;1&#xff09;在某一学科方面确有特长的学生&#…

谁将掌控工业界的命脉?揭秘工业互联网巨头的秘密角逐!

大数据产业创新服务媒体 ——聚焦数据 改变商业 在这个快速发展的数字化时代&#xff0c;一个新兴的巨兽——工业互联网&#xff0c;正以惊人的速度崛起&#xff0c;它不仅预示着生产力的飞跃性进步&#xff0c;更是引领着整个工业世界走向一个前所未有的新时代。 然而&#x…

微信小程序中路由跳转的方式有哪些?区别?

面试官&#xff1a;说说微信小程序中路由跳转的方式有哪些&#xff1f;区别&#xff1f; 一、是什么 微信小程序拥有web网页和Application共同的特征&#xff0c;我们的页面都不是孤立存在的&#xff0c;而是通过和其他页面进行交互&#xff0c;来共同完成系统的功能 在微信小…

【FPGA/verilog -入门学习17】vivado 实现串口自发自收程序

1&#xff0c;需求 PC使用串口助手给FPGA板发送9600 波特率的数据&#xff0c;FPGA板接收到数据后&#xff0c;回复同样的数据给PC 2&#xff0c;需求分析 按模块可以划分为&#xff1a; rx接收模块&#xff0c;将输入的8位并行rx 数据转换成[7:0]rx_data 信号&#xff0c;当…

C++面试宝典第18题:旋转数组

题目 给定一个数组,将数组中的元素向右移动k个位置,其中k是非负数。要求如下: (1)尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。 (2)使用时间复杂度为O(n)和空间复杂度为O(1)的原地算法解决这个问题。 示例 1: 输入: [1, 2, 3, 4, 5, 6, 7] 和 k…

NR中如何判断是否需要measurement gap来做邻区的测量?

先看下NR中定义的测量。 intra-freq 测量和inter-freq测量可以分为以下几类&#xff1a; 1 SSB based intra-freq 测量&#xff1a;serving cell SSB的center freq与邻区 SSB的center freq 相同并且两个SSB 的SCS也相同。 2 SSB based inter-freq 测量&#xff1a;serving ce…

vue3中ref和reactive联系与区别以及如何选择

vue3中ref和reactive区别与联系 区别 1、ref既可定义基本数据类型&#xff0c;也可以定义引用数据类型&#xff0c;reactive只能定义应用数据类型 2、ref在js中取响应值需要使用 .value&#xff0c;而reactive则直接取用既可 3、ref定义的对象通过.value重新分配新对象时依旧…

自学Python,需要注意哪些?

为什么要学习Python&#xff1f; 在学习Python之前&#xff0c;你不要担心自己没基础或“脑子笨”&#xff0c;我始终认为&#xff0c;只要你想学并为之努力&#xff0c;就能学好&#xff0c;就能用Python去做很多事情。在这个喧嚣的时代&#xff0c;很多技术或概念会不断兴起…

php 函数声明与调用

在 PHP 中&#xff0c;函数声明和调用的语法如下&#xff1a; 函数声明的一般形式为&#xff1a; function functionName($param1, $param2, ...) {// 函数体return $result; // 可选 } 例如&#xff1a; function add($a, $b) {return $a $b; } 函数调用的一般形式为&am…

Elasticsearch 地理空间搜索 - 远超 OpenSearch

作者&#xff1a;来自 Elastic Nathan_Reese 2021 年&#xff0c;OpenSearch 和 OpenSearch Dashboards 开始作为 Elasticsearch 和 Kibana 的分支。 尽管 OpenSearch 和 OpenSearch Dashboards 具有相似的血统&#xff0c;但它们不提供相同的功能。 在分叉时&#xff0c;只能克…

纯化蛋白质树脂ES-4060_用于吸附蛋白质树脂

蛋白纯化树脂是一种固定在基质中的化学物质&#xff0c;具有选择性地与目标蛋白结合&#xff0c;并通过洗脱将其从混合物中分离出来。蛋白纯化树脂的工作原理主要分为三个步骤:吸附、洗脱和再生。 吸附 蛋白纯化树脂通过与目标蛋白之间的特定相互作用来吸附目标蛋白。这些相互…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷5

某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenStack搭建企业内部私有云平台&#xff0c;开源Kubernetes搭建云原生服务平台&#xff0c;选…