react笔记-03react-router篇

本文章是react的路由笔记

一、react路由(v5版本)

1. 什么是路由(前端)?

  1. 一个路由就算一个映射关系(key: value)
  2. key为路径,value为组件

2. 前端路由的工作原理

根据浏览器历史记录:history(BOM)

3. 路由的基本使用(react-router-dom)

3.1 react-router:(有三种库)

  • web (react-router-dom)
  • react-native
  • any(react-router)

3.2 react-router-dom 的api(版本5/v5)

安装
npm i react-router-dom@5
内置组件
1. <BrowserRouter>
2. <HashRouter>
3. <Route>
4. <Redirect>
5. <Link>
6. <NavLink>
7. <Switch>
其他
  1. history 对象
  2. match 对象
  3. withRouter 函数

3.3 基本使用

App.js中

import { Component } from 'react'
import { Link, Route } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'export default class App extends Component {render() {return {<div><header>{/* 编写路由链接 */}<Link to="/home">首页</Link><Link to="/about">关于</Link></header><main>{/* 注册路由 */}<Route path="/home" component={Home} /><Route path="/about" component={About} /></main></div>}}
}

index.js中

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter, HashRouter } from 'react-router-dom'
import App from './App'ReactDOM.render({/* history路由 */}<BrowserRouter><App /></BrowserRouter>{/* hash路由 */}<HashRouter></HashRouter>, document.querySelect('#root'))

3.4 路由组件与一般组件

一般组件的props信息需要通过父组件传递,而路由组件的props信息是路由信息,不需要传递。

3.5 NavLink的使用

  1. NavLink的基本使用

匹配上的路由会默认加上active这个类名

<NavLink to="/home">首页</NavLink>
<NavLink to="/about">关于</NavLink>

通过activeClassName可以自定义选中的类名

<NavLink to="/home" activeClassName="header-active">首页</NavLink>
<NavLink to="/about" activeClassName="header-active">关于</NavLink>
  1. NavLink的封装

组件的使用:

{/* 「首页」标题:组件标签标签体内容(特殊的标签属性,组件内可以通过this.props.children获取) */}
<MyNavLink to="/home">首页</MyNavLink>
<MyNavLink to="/about">关于</MyNavLink>

组件的封装:

{/* 一组props */}
<NavLink to={to} activeClassName="header-active">首页</NavLink>
{/* 多组props */}
<NavLink {...this.props} activeClassName="header-active"/>

3.6 Switch的使用

Switch:当匹配到第一个路由的时候就停止

<Switch><Route path="/home" component={Home} /><Route path="/about" component={About} /><Route path="/about" component={Demo} />
</Switch>

3.7 路由的模糊匹配与精准匹配

模糊匹配:

<header><NavLink to="/about/a/b">关于</NavLink>
</header>
<main><Switch><Route path="/about" component={About} /></Switch>
</main>

精准匹配:exact={true}

<Route exact={true} path="/about" component={About} />

3.8 Redirect的使用

Redirect(重定向):谁都匹配不上,就走Redirect

<Switch><Route path="/home" component={Home} /><Route path="/about" component={About} /><Redirect to="/about" />
</Switch>

3.9 嵌套路由

嵌套路由要写完整路径

<div><NavLink to="/home/news">News</NavLink><NavLink to="/home/message">Message</NavLink>
</div>
<div><Switch><Route path="/home/news" component={News} /><Route path="/home/message" component={Message} /></Switch>
</div>

3.10 路由组件传参

1. 向路由组件传递params参数

传递的参数:

<NavLink to={`/home/news/${title}/${page}`}>News</NavLink>
<Route path="/home/news/:title/:page" component={News} />

News组件可以通过this.props.match.params获取到params参数

2. 向路由组件传递search(query)参数(显式传参)

使用:

<NavLink to={`/home/news?title=${title}&page=${page}`}>News</NavLink>{/* search参数无需声明接收,正常注册路由即可 */}
<Route path="/home/news" component={News} />

接收:

接收到的search参数是urlencoded编码的字符串,需要借助querystring解析

key=value&key=value => urlencoded编码

安装query-string

npm i query-string
import qs from 'query-string'qs.parse(this.props.location.search)
3. 向路由组件传递state参数(隐式传参)

使用:

<NavLink to={{pathname: '/home/news', state: { title, page }}}>News</NavLink>{/* state参数无需声明接收,正常注册路由即可 */}
<Route path="/home/news" component={News} />

接收:

通过this.props.location.state接收,BrowserRouter刷新参数不丢失,HashRouter刷新参数丢失

3.11 push与replace模式

  • push:会留下痕迹,可以通过回退键,回到上一页
  • replace:不会留下痕迹,不能回到上一页

3.12 编程式路由导航

// 路由跳转
this.props.history.replace('/xxx', [state])
this.props.history.replace('/xxx', { id, title })
this.props.history.push('/xxx', [state])
this.props.history.push('/xxx', { id, title })
// 路由前进
this.props.history.goForward()
// 路由后退
this.props.history.goBack()
// 与vue中的go类似,传入number,正数表示前进,负数表示后退
this.props.history.go(number)

3.13 withRouter的使用

在一般组件内,不能像路由组件一样获取到路由信息,需要在组件上包裹一个withRouterwithRouter可以加工一般组件,让一般组件具备路由组件所特有的api,withRouter的返回值是一个新组件。

import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'class App extends Component {handleClick = () => {console.log(this.props)}render() {return (<div onClick={this.handleClick}>关于</div>)}
}export default withRouter(App)

二、react路由(v6版本)

1. Component

1.1 <Routes/><Route/>

  1. v6版本中移除了之前的<Switch>,用<Routes>代替

  2. <Routes/><Route/>要配合使用,且必须要用<Routes>包裹<Route>

  3. <Route caseSensitive>属性用于指定:匹配时是否区分大小写(默认为false)

  4. <Route>也可以嵌套使用,且可配合useRoutes()配置路由表,但需要通过<Outlet>组件来渲染其子路由

  5. <Route>end属性:如果他的子路由匹配,父亲路由失去高亮

  6. 写法区别:

    import { Routes, Route, Navigate } from 'react-router-dom'{/* Switch组件 替换成 Routes */}
    <Routes>{/* Route的component属性变成element属性 */}{/* v5写法:<Route path='/' component={Home} /> */}{/* v6写法:<Route path='/' element={<Home />} /> 写成标签 */}<Route caseSensitive path='/home' element={<Home />} /><Route path='/about' element={<About />} />{/* 重定向,不用Redirect,而是Navigate */}{/* 用法:<Navigate to="/home" replace={true} /> */}{/* replace跳转模式:push/replace模式,默认false(push) */}<Route path='/' element={<Navigate to="/home" />} />{/* end属性:如果他的子路由匹配,父亲路由失去高亮 */}	<Route path='/' end element={<Navigate to="/home" />} />
    </Routes>
    

1.2 <NavLink>

  1. 自定义选中的高亮样式

    {/* v5写法 */}
    <NavLink activeClassName="xxx">
    {/* v6写法:在className属性中写入函数,函数返回类名 */}
    <NavLink to='/home' className={({isActive}) => { return isActive ? 'item active' : 'item' }}>Home</NavLink>
    
    <NavLink to='/home' className={(e) => {console.log(e);}}>Home</NavLink>
    

    下面是的参数e:

    在这里插入图片描述

1.3 <Navigate>

  1. <Navigate>:重定向,不用Redirect,而是Navigate。渲染到页面上,会让路由进行跳转。
  2. 用法:<Navigate to="/home" />
  3. replace属性:路由跳转模式,push/replace模式,默认false(push)<Navigate to="/home" replace={true} />

2. Hooks

2.1 useRoutes()

注册路由:

  • 写法1:
{/* 注册路由 */}
<Routes><Route path='/home' element={<Home />} /><Route path='/about' element={<About />} /><Route path='/' element={<Navigate to="/home" />} />
</Routes>
  • 写法2:由useRoutes生成路由表
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 routeElement = useRoutes([{path: '/home',element: <Home />},{path: '/about',element: <About />},{path: '/',element: <Navigate to="/home" />}])return (<div><NavLink to='/home'>Home</NavLink> | <NavLink to='/about'>About</NavLink><hr />{/* 注册路由 */}{ routeElement }</div>)
}

2.2 嵌套路由

在路由表添加children属性即可

const routeElement = useRoutes([{path: '/home',element: <Home />},{path: '/about',element: <About />,children: [{path: 'news',element: <div>news</div>},{path: 'message',element: <div>message</div>}]},{path: '/',element: <Navigate to="/home" />}
])

About组件中,需要一个路由出口,用Outlet来展示二级子路由

import React from 'react'
import { NavLink, Outlet } from 'react-router-dom'export default function index() {return (<div>About<br />{/* v5写法 */}<NavLink to="/about/news">news</NavLink> | <NavLink to="/about/message">message</NavLink>{/* v6中:同v5,也可以只写子路由路径,但是不能带斜杠,类似于vue */}<NavLink to="news">news</NavLink> | <NavLink to="message">message</NavLink>{/* 路由出口 */}<Outlet /></div>)
}

2.3 useParams()(获取params参数)

useParams()获取传递的params参数

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

2.4 useMatch()(获取params参数)

useMatchuseParams都可以用来读取params参数

使用:useMatch('/home/:id/:title')

2.5 useSearchParams()(获取search参数)

useSearchParams用来获取search(query)参数,返回的是一个数组

  1. searchParams:获取到search参数,但是需要通过get()方法获取
// 我的url为http://localhost:5173/about/news?id=1&title=haha
const [searchParams, setSearchParams] = useSearchParams()
// 需要通过get方法,传入key,获取到value
let id = searchParams.get('id'))
  1. setSearchParams:更改search参数
setSearchParams('id=2&title=hello')

2.6 useLocation()(获取search、state参数)

  1. 获取search参数:

useLocationuseSearchParams都可以获取search参数,不用像useMatch那样传递路径。

  1. 获取state参数:

传递state参数(隐式传参):

{/* v5写法 */}
<NavLink to={{ pathname: '/home', state: {name: 'xiaotian', age: 20} }}>Home</NavLink>
{/* v6写法 */}
<NavLink to='/home' state={{ name: 'xiaotian', age: 20 }}>Home</NavLink>
  1. 使用useLocation()
// 对象的连续解构
const { state: {name, age} } = useLocation()

2.7 路由传参总结

params => useParams、useMatch

search(query) => useSearchParams、useLocation

state => useLocation

2.8 编程式路由导航

let navigate = useNavigate()
// 1. 基本使用
navigate('/about')
// 2. 子路由
navigate('news')
// 3. 传递state参数
navigate('news', {replace: false,state: {name: 'xiaotian',age: 20},
})
// 4. 前进
navigate(1)
// 5. 后退
navigate(-1)

2.9 useInRouterContext()

  1. 作用:用于判断组件是否被路由包裹着
  2. 返回值:boolean

2.10 useNavigationType()

  1. 作用:返回当前的导航类型(用户是如何来到当前页面的)
  2. 返回值:poppushreplace
  3. 备注:pop是指直接在浏览器中打开了这个路由组件(复制链接、刷新进入)

2.11 useOutlet()

  1. 作用:用来呈现当前组件中渲染的嵌套路由
  2. 返回值:如果嵌套路由没有挂载,则res返回null;如果嵌套路由已经挂载,则展示嵌套路由对象。
let res = useOutlet()

2.12 useResolvedPath

作用:给定一个url值,解析其中的pathsearchhash值。

三、项目中如何配置路由表(v6版本)

1. 标签形式

  1. src下创建router目录,新建index.jsx

这里用到了嵌套路由的写法

import { BrowserRouter, Routes, Route } from 'react-router-dom'
import App from '../App'
import Home from '../views/Home/Home'
import About from '../views/About/About'const baseRouter = () => {return (<BrowserRouter><Routes>{/* 嵌套路由写法 */}<Route path='/' element={<App />}><Route path='/home' element={<Home />}></Route><Route path='/about' element={<About />}></Route></Route></Routes></BrowserRouter>)
}export default baseRouter
  1. main.jsx中将原有的App根组件替换成路由表组件
import ReactDOM from 'react-dom/client'
import BaseRouter from './router/index.jsx'ReactDOM.createRoot(document.getElementById('root')).render(<BaseRouter />,
)
  1. App.jsx中配置路由出口
import { Outlet } from 'react-router-dom'export default function App() {return (<div>{/* 占位符,用于展示组件,类似于vue的router-view(路由出口) */}<Outlet /></div>)
}

2. Hook形式

2.1 基本使用

  1. src下创建router目录,新建index.jsx
import { Navigate } from 'react-router-dom'
import Home from '../views/Home/Home'
import About from '../views/About/About'const routes = [// 当App组件使用了useRoutes渲染路由时,就不允许在路由表中配置App组件有关的路由// 错误写法:会导致页面不停渲染,最终卡死// {//     path: '/',//     element: <App />// },{path: '/',element: <Navigate to="/home" />},{path: '/home',element: <Home />},{path: '/about',element: <About />},// 错误页面,重定向到404{path: '*',element: <Navigate to="/404" />}
]export default routes
  1. main.jsx中用BrowserRouterHashRouter包裹一下根组件
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App.jsx'ReactDOM.createRoot(document.getElementById('root')).render(<BrowserRouter><App /></BrowserRouter>,
)
  1. App.jsx中渲染路由
import { useRoutes } from 'react-router-dom'
import router from './router'export default function App() {const outlet = useRoutes(router)return (<div>// 渲染路由{ outlet }</div>)
}

2.2 路由懒加载

router/index.jsx中,使用lazy即可实现路由的懒加载

import { lazy } from 'react'const Home = lazy(() => import('../views/Home/Home'))

但是通常情况下,lazySuspense是结合使用的,不然会出现报错(但是我目前写lazy没有出现报错),可以通过如下代码书写我们的懒加载路由:

import { lazy, Suspense } from 'react'
import { Navigate } from 'react-router-dom'const Home = lazy(() => import('../views/Home/Home'))
const About = lazy(() => import('../views/About/About'))const routes = [{path: '/',element: <Navigate to="/home" />},{path: '/home',element: (// 当路由很多时,书写这段代码会显得非常繁琐,可以封装一个withLoadingComponent方法<Suspense fallback={<div>loading...</div>}><Home /></Suspense>)},{path: '/about',element: withLoadingComponent(<About />),}
]// comp的ts类型为JSX.Element
const withLoadingComponent = (comp) => {return (<Suspense fallback={<div>loading...</div>}>{ comp }</Suspense>)
}export default routes

2.3 嵌套路由

路由表通过children属性可以书写子路由,但是子路由并不会直接展示在页面上,需要通过在展示子路由的页面上放置路由出口<Outlet />

路由表配置:

const routes = [{path: '/',element: <Navigate to="/home" />},{path: '/home',element: <Home />},{path: '/about',element: <About />,// 子路由children: [{path: '/about/news',element: <News />}]}
]

路由出口:(在About组件内)

import React from 'react'
import { Outlet } from 'react-router-dom'export default function about() {return (<div>about<Outlet /></div>)
}

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

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

相关文章

双例集合(三)——双例集合的实现类之TreeMap容器类

Map接口有两个实现类&#xff0c;一个是HashMap容器类&#xff0c;另一个是TreeMap容器类。TreeMap容器类的使用在API上于HashMap容器类没有太大的区别。它们的区别主要体现在两个方面&#xff0c;一个是底层实现方式上&#xff0c;HashMap是基于Hash算法来实现的吗&#xff0c…

什么是电商大数据?主流电商大数据的采集||关键性技术|电商API接口接入说明

大数据的时代早已到来&#xff0c;然而想要全方位掌握大数据&#xff0c;务必要掌握大数据造成的时代特征&#xff0c;之前大数据被视为废物&#xff0c;如今被视为财产。主流电商大数据的采集&#xff0c;电商API接口的接入在大多数人理解中&#xff0c;是企业用数据来优化自己…

HackTheBox-Linux基础

Linux 结构 历史 许多事件导致了第一个 Linux 内核的创建&#xff0c;并最终创建了 Linux 操作系统 &#xff08;OS&#xff09;&#xff0c;从 1970 年 Ken Thompson 和 Dennis Ritchie&#xff08;当时都在 AT&T 工作&#xff09;发布 Unix 操作系统开始。伯克利软件发行…

微信小程序毕业设计-餐厅点餐系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

OCC显示渲染结构剖析

1.Display显示 2.Drawer 3.Graphics 4.InteractiveContext 5.Render 6.Selection 7.View

图像分割(四)---(图像显示、灰度直方图和三维灰度图综合分析选取最佳分割方法)

一、引言 对彩色图像进行分割的一种常用方法&#xff0c;是先把彩色图像转灰度图像&#xff0c;然后再选择合适的阈值进行二值分割。但有时彩色图像转灰度图像后不具有典型的双峰特性&#xff0c;二值分割效果不好。本文章提出一种确定彩色图像分割方法的新思路。首先读入一幅彩…

以太坊==给合约转入/查询合约剩余/合约转给某账户/结构体/MAP

转入 必须要定义该函数&#xff0c;或者定义fallback // 接收以太币 receive() external payable {} // Corrected Line // SPDX-License-Identifier: MIT pragma solidity ^0.8.0;contract SimpleStorage {uint256 private storedData;// 事件&#xff0c;用于通知数据变更e…

Java-异常:不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获

Java-异常&#xff1a;不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获 Java-异常&#xff1a;不恰当的异常转换、不充分的日志记录、过度或不当的异常捕获一、前期准备二、案例分析1、不恰当的异常转换2、不充分日志记录3、过度或不当的异常捕获 三、正确处理方式1…

Open WebUI – 本地化部署大模型仿照 ChatGPT用户界面

Open WebUI介绍&#xff1a; Open WebUI 是一个仿照 ChatGPT 界面&#xff0c;为本地大语言模型提供图形化界面的开源项目&#xff0c;可以非常方便的调试、调用本地模型。你能用它连接你在本地的大语言模型&#xff08;包括 Ollama 和 OpenAI 兼容的 API&#xff09;&#xf…

emqx5.6.1 数据、配置备份与迁移

EMQX 支持导入和导出的数据包括&#xff1a; EMQX 配置重写的内容&#xff1a; 认证与授权配置规则、连接器与 Sink/Source监听器、网关配置其他 EMQX 配置内置数据库 (Mnesia) 的数据 Dashboard 用户和 REST API 密钥客户端认证凭证&#xff08;内置数据库密码认证、增强认证…

公共网络IP地址不正确?别担心,这里有解决方案

在数字化时代&#xff0c;公共网络IP地址的正确性对于我们的在线体验至关重要。它不仅是网络连接的标识&#xff0c;更是确保我们正常访问互联网资源、享受网络服务的基础。然而&#xff0c;有时我们可能会遇到公共网络IP地址不正确的情况&#xff0c;这不仅会影响我们的网络速…

【已解决】SpringBoot图片更新需重启服务器才能显示

问题描述 1、更新头像&#xff0c;并跳转回列表页&#xff0c;发现显示不出来 2、但是前端获取用户头像的信息是在加载页面就会被调用的&#xff0c;同时前端也不存在所谓的缓存问题&#xff0c;因为没有动这部分代码。 但查看响应是能获得正确的信息&#xff08;前端打印图片…

数据结构--单链表(图文)

单链表的概念 在单链表中&#xff0c;每个元素&#xff08;称为节点&#xff09;包含两部分&#xff1a;一部分是存储数据的数据域&#xff0c;另一部分是存储下一个节点地址的指针域。这里的“单”指的是每个节点只有一个指向下一个节点的指针。 节点&#xff1a;链表中的基…

Apple - Secure Coding Guide

本文翻译整理自&#xff1a;Secure Coding Guide https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Introduction.html#//apple_ref/doc/uid/TP40002477-SW1 文章目录 一、安全编码指南简介1、概览黑客和攻击者没有平台是免疫…

【办公类-50-01】20240620自主游戏观察记录表19周内容打乱

背景需求&#xff1a; 又到了期末&#xff0c;各种班级资料需要提交。 有一份自主游戏观察记录需要写19周&#xff08;每周2次&#xff09;的观察记录&#xff0c;并根据参考书填写一级、三级、五级的评价指标。 去年中六班的时候&#xff0c;我很认真的手写了21周的户外游戏…

具有 Hudi、MinIO 和 HMS 的现代数据湖

Apache Hudi 已成为管理现代数据湖的领先开放表格式之一&#xff0c;直接在现代数据湖中提供核心仓库和数据库功能。这在很大程度上要归功于 Hudi 提供了表、事务、更新/删除、高级索引、流式摄取服务、数据聚类/压缩优化和并发控制等高级功能。 我们已经探讨了 MinIO 和 Hudi…

Vue3 - 在项目中使用vue-i18n不生效的问题

检查和配置 Vue I18n 确保你已经正确安装了Vue I18n并且配置了组合API模式。 安装 Vue I18n npm install vue-i18nnext配置 i18n.js import { createI18n } from vue-i18n; import messages from ./messages;const i18n createI18n({legacy: false, // 使用组合 API 模式l…

Linux检查端口nmap

yum install -y nmap # 查看本机在运行的服务的端口号 nmap 127.0.0.1 补充&#xff1a;netstat netstat -tunlp | grep 3306

读《文明之光》第2册总结

《文明之光》系列大致按照从地球诞生到近现代的顺序讲述了人类文明进程的各个阶段&#xff0c;每个章节相对独立&#xff0c;全景式地展现了人类文明发展历程中的多样性。《文明之光》系列第二册讲述了从近代科学兴起&#xff0c;到工业革命时代&#xff0c;以及原子能应用这一…

C++/Qt 小知识记录7

工作中遇到的一些小问题&#xff0c;总结的小知识记录&#xff1a;C/Qt 小知识7 编译FFMPEG遇到的问题CMakeLists.txt配置FFMPEG的依赖方式&#xff1a; x264在Windows下编译生成*.libVS编译Qt工程时&#xff0c;遇到提示Change Qt Version的情况在QtOsg的窗口上嵌入子窗口&…