React(七):Router基本使用、嵌套路由、编程式导航、路由传参、懒加载

news2024/11/17 19:46:36

React(七)

  • 一、React-Router的基本使用
    • 1.安装和介绍
    • 2.路由的配置和跳转
    • 3.Navigate的使用
    • 4.如果找不到对应的路由路径?
  • 二、嵌套路由的用法
  • 三、编程式路由导航
    • 1.类组件中使用useNavigate
    • 2.函数式组件中使用useNavigate
  • 四、路由跳转传参
    • 1.设置好路径的占位符(params)
    • 2.参数直接拼接到url中(query)
  • 五、路由的配置文件
  • 六、路由的懒加载

一、React-Router的基本使用

1.安装和介绍

安装:

npm install react-router-dom

react-router最主要的API是给我们提供的一些组件:BrowserRouterHashRouter

其中BrowserRouter使用history模式;

import React from "react"
import ReactDOM from "react-dom/client"
import { BrowserRouter } from "react-router-dom"
import App from "./App"

const root = ReactDOM.createRoot(document.querySelector("#root"))

root.render(
  <BrowserRouter>
    <App/>
  </BrowserRouter>
)

HashRouter使用hash模式:

import React from "react"
import ReactDOM from "react-dom/client"
import { HashRouter } from "react-router-dom"
import App from "./App"

const root = ReactDOM.createRoot(document.querySelector("#root"))

root.render(
  <HashRouter>
    <App/>
  </HashRouter>
)

2.路由的配置和跳转

在App中通过使用Routes和Route组件指定路由的出口,path属性指定对应路径,element属性指定要切换的组件实例。

通过Link组件实现路由的跳转,to属性指定切换的路径

import React, { PureComponent } from 'react';
import Home from './pages/Home';
import Search from './pages/Search';
import Detail from './pages/Detail';
import {Routes, Route, Link} from 'react-router-dom';

export class App extends PureComponent {
  render() {
    return (
      <div>
        <div className="header">
          Header<hr />
          <Link to='/home'>点击切换到Home</Link><hr />
          <Link to='/detail'>点击切换到detail</Link><hr />
          <Link to='/search'>点击切换到search</Link><hr />
        </div>
        <div className="content">
          中间的路由内容
          <Routes>
            <Route path='/home' element={<Home />} />
            <Route path='/detail' element={<Detail />} />
            <Route path='/search' element={<Search />} />
          </Routes>
        </div>
        <div className="foorer">Footer</div>
      </div>
    )
  }
}

export default App

在这里插入图片描述

3.Navigate的使用

Navigate用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中

比如我们举个例子,用户来到登录页:
如果没登陆就显示登录按钮;
如果点击登录按钮,就把状态设置为登录,然后就自动跳转到home页。

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

export class Login extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isLogin: false
    }
  }

  login() {
    this.setState({
      isLogin: true
    })
  }
  render() {
    let { isLogin } = this.state;
    return (
      <div>
        <h1>Login</h1>
        {!isLogin ? <button onClick={(() => this.login())}>登录</button> : <Navigate to='/home'/>}
      </div>

    )
  }
}

export default Login

还有就是路由的重定向问题,如果遇到地址只有一个/,那么就导航至home页(或者其实直接写Home组件 <Route path='/' element={<Home />} />也可以的)

  <Routes>
    <Route path='/' element={<Navigate to='/home' />} />
    <Route path='/home' element={<Home />} />
    <Route path='/detail' element={<Detail />} />
    <Route path='/login' element={<Login />} />
  </Routes>

4.如果找不到对应的路由路径?

此时我们可以设置path='*'时(找不到路径时),自动路由跳转到某个组件,给用户提示

  <Routes>
    <Route path='/' element={<Navigate to='/home' />} />
    <Route path='/home' element={<Home />} />
    <Route path='/detail' element={<Detail />} />
    <Route path='/login' element={<Login />} />
    <Route path='*' element={<NotFound />} />
  </Routes>

在这里插入图片描述

二、嵌套路由的用法

在vue中我们需要去配置children这个配置项,但是在react中,不需要噢。

比如我要在Home里面搞个导航栏切换对应的内容:

在这里插入图片描述
那么首先先建三个组件:

在这里插入图片描述

然后来到App,在Home页的这个Route标签中间写嵌套的路由,这里的第一行是一个重定向,如果进入Home页,默认导航至第一个组件Column1

在这里插入图片描述
然后回到Home页,设置跳转的标签和子路由的出口<Outlet>

在这里插入图片描述

当然啊Outlet啊,Route啊,Link啊这些组件别忘了引入。

三、编程式路由导航

React-router给我们提供了一个hook,名字叫useNavigate,调用它可以返回一个函数,我们调用这个函数并把path传给它就可以实现随时通过点击事件进行路由的跳转。

但是既然是hook,那么就只能在函数式组件中使用,如果要在类组件中使用呢?

1.类组件中使用useNavigate

在类组件中想要使用hook并不是不可以,我们可以通过一个高阶组件,给类组件注入这个hook,然后通过props就能调用并传参。

在做高阶组件时,返回的应该是一个函数式组件(如果是类组件不还是用不了吗),然后把useNavigate的返回值(一个函数)注入进去

import { useNavigate } from "react-router-dom";

export default function enhanceUseNavigate(Component) {
    //这里要通过函数式组件注入,因为类组件里不能用噢
    return function(props) {
        let navigate = useNavigate();
        return <Component {...props} navigate={navigate}/>
    }
}

然后另一边使用高阶组件,并且点击按钮时调用传path就行了,这样就可以实现跳转。

export class App extends PureComponent {
  navigateTo(path) {
    //在这里就可以调用注入的跳转函数,传入path进行路由跳转
    this.props.navigate(path);
  }

  render() {
    return (
      <div>
        <div className="header">
          Header<hr />
          <button onClick={() => this.navigateTo('/home')}>点击按钮跳转到Home</button>
          <button onClick={() => this.navigateTo('/detail')}>点击按钮跳转到detail</button>
          <button onClick={() => this.navigateTo('/login')}>点击按钮跳转到登录页</button>
        </div>
        <div className="content">
          <h4>中间的路由内容:</h4>
          <Routes>
            <Route path='/' element={<Navigate to='/home' />} />
            <Route path='/home' element={<Home />} />
            <Route path='/detail' element={<Detail />} />
            <Route path='/login' element={<Login />} />
            <Route path='*' element={<NotFound />} />
          </Routes>
        </div>
        <div className="foorer">Footer</div>
      </div>
    )
  }
}

export default enhanceUseNavigate(App);

2.函数式组件中使用useNavigate

这东西本来就是为函数式组件而生的,所以在这里使用简直是妙蛙种子到了米奇妙妙屋,妙到家了。

function App() {
  let navigate = useNavigate();
  
  function navigateTo(path) {
    navigate(path);
  }

  return (
      <div>
        <div className="header">
          Header<hr />
          <button onClick={() => this.navigateTo('/home')}>点击按钮跳转到Home</button>
          <button onClick={() => this.navigateTo('/detail')}>点击按钮跳转到detail</button>
          <button onClick={() => this.navigateTo('/login')}>点击按钮跳转到登录页</button>
        </div>
        <div className="content">
          <h4>中间的路由内容:</h4>
          <Routes>
            <Route path='/' element={<Navigate to='/home' />} />
            <Route path='/home' element={<Home />} />
            <Route path='/detail' element={<Detail />} />
            <Route path='/login' element={<Login />} />
            <Route path='*' element={<NotFound />} />
          </Routes>
        </div>
        <div className="foorer">Footer</div>
      </div>
    )
}

export default App;

四、路由跳转传参

1.设置好路径的占位符(params)

类似于vue中的params参数
注意,写了占位,如果不传,那么路径就会置空

在这里插入图片描述

通过拼接:参数名可以设置参数的key,这样的话就可以把参数的value通过Link或编程式导航传给Detail组件。

那么参数怎么接呢?

这里要提到另一个hook用来接收参数,useParams,但是呢如果Detail组件是一个类组件,那么我们就要用高阶组件给它注入这个东西:

拿刚才那个高阶组件举例吧,还是同样的方法,把params注入给Detail的props。

import { useNavigate, useParams } from "react-router-dom";

export default function enhanceUseNavigate(Component) {
    //这里要通过函数式组件注入,因为类组件里不能用噢
    return function (props) {
        let navigate = useNavigate();
        let params = useParams();
        let router = { navigate, params };
        return <Component {...props} router={router} />
    }
}

最后来到Detail组件,可以直接读取,参数传过来放到对象里,我们就能去读它的id,或者用它发请求什么的。

import React, { PureComponent } from 'react';
import enhanceUseNavigate from '../utils/enhanceUseNavigate';

export class Detail extends PureComponent {
  render() {
    let { params } = this.props.router;
    console.log(params);//{id: '123'}
    return (
      <div>
        <h1>Detail</h1>
        <h2>收到路由跳转传来的参数:{params.id}</h2>
      </div>
    )
  }
}

export default enhanceUseNavigate(Detail)

2.参数直接拼接到url中(query)

类似vue中的query参数

在这里插入图片描述
直接在跳转的地方拼接url参数,那么怎么接呢?

这里用到另一个hook:useSearchParams

当然在函数式组件中用会比较合适,但是这里我们在类中演示吧,还是用高阶组件,拿之前那个举例:

import { useNavigate, useParams, useSearchParams } from "react-router-dom";

export default function enhanceUseNavigate(Component) {
    //这里要通过函数式组件注入,因为类组件里不能用噢
    return function (props) {
        // 1.导航
        const naviagte = useNavigate()

        // 2.动态路由的参数
        const params = useParams()

        // 3.查询字符串的参数
        const [searchParams] = useSearchParams()
        // console.log(searchParams.get('name'))
        const query = Object.fromEntries(searchParams.entries())
        console.log(query);
        const router = { naviagte, params, query}

        return <Component {...props} router={router} />
    }
}

这里的写法没怎么见过,先记住吧。总之就是把传过来的url参数变成一个对象,里面存着键值对格式的参数。同样我们注入到Login组件中,就可以接到参数了

import React, { PureComponent } from 'react'
import enhanceUseNavigate from '../utils/enhanceUseNavigate';;

export class Login extends PureComponent {
  render() {
    let { query } = this.props.router;
    return (
      <div>
        <h1>Login</h1>
        <h2>拿到query参数!{query.name}-{query.age}</h2>
      </div>
    )
  }
}

export default enhanceUseNavigate(Login)

五、路由的配置文件

目前我们所有的路由都配置在组件中,用标签的形式写出来的,这样会比较乱,那么我们想像vue一样有自己的独立配置,react给我们提供了这样的hook

比如我们要把下面这一堆路由关系配置成一个单独的文件

<div className="content">
  <h4>中间的路由内容:</h4>
   <Routes>
     <Route path='/' element={<Navigate to='/home' />} />
     <Route path='/home' element={<Home />} >
       <Route path='/home' element={<Navigate to='/home/column1' />}></Route>
       <Route path='/home/column1' element={<Column1 />}></Route>
       <Route path='/home/column2' element={<Column2 />}></Route>
       <Route path='/home/column3' element={<Column3 />}></Route>
     </Route>
     <Route path='/detail/:id' element={<Detail />} />
     <Route path='/login' element={<Login />} />
     <Route path='*' element={<NotFound />} />
   </Routes>
 </div>

大概就是这样的:

import Home from '../pages/Home';
import Login from '../pages/Login';
import Detail from '../pages/Detail';
import NotFound from '../pages/NotFound';
import Column1 from '../pages/Column1';
import Column2 from '../pages/Column2';
import Column3 from '../pages/Column3';
import { Navigate } from 'react-router-dom';

let routes = [
    {
        path:'/',
        element: <Navigate to='/home'/>  //重定向
    },
    {
        path:'/home',
        element: <Home/>,
        children: [
            {
                path:'/home',
                element: <Navigate to="/home/column1"/> //重定向
            },
            {
                path:'/home/column1',
                element: <Column1/>
            },
            {
                path:'/home/column2',
                element: <Column2/>
            },
            {
                path:'/home/column3',
                element: <Column3/>
            }
        ]
    },
    {
        path:'/detail/:id',
        element: <Detail/>
    },
    {
        path:'/login',
        element: <Login/>
    },
    {
        path: '*',
        element: <NotFound/>
    }
]

export default routes;

然后在App中需要导入routes,并且使用hook占位:

在这里插入图片描述
ok搞定

六、路由的懒加载

两步
1、换成这个

在这里插入图片描述
2、包个标签

import { Suspense } from 'react';
......
root.render(
  <HashRouter>
    <Suspense fallback={<h3>路由懒加载加载中!!</h3>}>
      <App />
    </Suspense>
  </HashRouter>
);

这里fallback里的东西是加载没出来的时候显示的东西

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

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

相关文章

小白学Pytorch 系列--Torch API(1)

小白学Pytorch 系列–Torch API Torch version 1.13 Tensors TORCH.IS_TENSOR 如果obj是PyTorch张量&#xff0c;则返回True。 注意&#xff0c;这个函数只是简单地执行isinstance(obj, Tensor)。使用isinstance 更适合用mypy进行类型检查&#xff0c;而且更显式-所以建议使…

【计组】主存储器有关知识梳理

一、主存储器 主存储器可以直接和CPU进行通信&#xff0c;但是只能保存临时数据&#xff0c;在断电后数据就消失。还有一个特点是&#xff0c;主存储器的容量小&#xff0c;速度快&#xff0c;造价高。 1.构成 2.主存中存储体的构造 最小的存储单位是存储元&#xff0c;存储元…

近亿美元:人工心脏龙头永仁心医疗完成超大额A轮融资

近日&#xff0c;永仁心医疗器械有限公司&#xff08;以下简称“永仁心医疗”&#xff09;完成近一亿美元A轮融资&#xff0c;由北京科兴中维生物技术有限公司&#xff08;SINOVAC科兴&#xff09;领投&#xff0c;太平&#xff08;深圳&#xff09;医疗健康产业私募股权投资基…

腾讯IM h5版本,在安卓原生和IOS原生支持情况的调查以及踩坑、解决办法

介绍 公司准备基于腾讯IM进行开发即时通讯功能&#xff0c;想用H5来开发&#xff0c;这样方便以后移植&#xff0c;在原生app里直接加载&#xff0c;通过三天时间的调查&#xff0c;以及与腾讯客服&#xff0c;技术来回沟通&#xff0c;已经有一定的成果&#xff0c;现将调查成…

【Redis】Redis持久化(一)

目录 1.Redis持久化 1.1.RDB持久化 1.1.1.执行时机 1.1.2.RDB原理 1.1.3.小结 1.2.AOF持久化 1.2.1.AOF原理 1.2.2.AOF配置 1.2.3.AOF文件重写 1.3.RDB与AOF对比 1.Redis持久化 Redis有两种持久化方案&#xff1a; RDB持久化 AOF持久化 1.1.RDB持久化 RDB全称Red…

SpringBoot - 什么是跨域?如何解决跨域?

什么是跨域&#xff1f; 在浏览器上当前访问的网站&#xff0c;向另一个网站发送请求&#xff0c;用于获取数据的过程就是跨域请求。 跨域&#xff0c;是浏览器的同源策略决定的&#xff0c;是一个重要的浏览器安全策略&#xff0c;用于限制一个 origin 的文档或者它加载的脚本…

Doris集成其他系统——ODBC外部表

Doris集成其他系统——ODBC外部表 文章目录Doris集成其他系统——ODBC外部表0. 写在前面1. 正文1.1 ODBC外部表介绍1.2 使用方式2. 使用 ODBC 的 MySQL 外表2.1 前置芝士2.2 安装 unixODBC2.3 安装MySQL 对应版本的 ODBC2.3.1 安装方式2.3.2 检查安装结果2.3.3 其他节点的安装及…

prometheus 配置服务器监控、服务监控、容器中服务监控与告警

最近公司有几个服务遇到了瓶颈&#xff0c;也就是数据量增加了&#xff0c;没有人发现&#xff0c;这不是缺少一个监控服务和告警的系统吗&#xff1f; 主要需求是监控每个服务&#xff0c;顺带监控一下服务器和一些中间件&#xff0c;这里采集的2种&#xff0c;zabbix和prom…

Kafka 消费者组

Kafka 消费者组Consumer数位移重平衡消费者组 (Consumer Group) : 可扩展且容错性的消费者机制 一个组内可能有多个消费者 (Consumer Instance) : 共享一个公共 ID (Group ID)组内的所有消费者协调消费订阅主题 (Subscribed Topics) 的所有分区 (Partition)每个分区只能由同个…

【1】熟悉刷题平台操作

TestBench使用 与quartus中testbench的写法有些许。或者说这是平台特有的特性&#xff01;&#xff01; 1 平台使用谨记 &#xff08;1&#xff09;必须删除&#xff1a;若设计为组合逻辑&#xff0c;需将自动生成的clk删除 若不删除&#xff0c;会提示运行超时错误。 &#…

git推送指定的提交到远程分支详细方法

默认情况下&#xff0c;git push会推送暂存区所有提交&#xff08;也即HEAD及其之前的提交&#xff09;到远程库&#xff0c;实际开发中可能因为功能没有开发完成&#xff0c;但是又必须提交部分修改好的代码就需要用到推送指定commit到远程分支。第一种方式&#xff1a;即符合…

CSS流动布局-页面自适应

项目中经常会碰到页面自适应的问题&#xff0c;例如&#xff1a;商城的列表展示、分类列表展示等页面&#xff0c;如下&#xff1a; 该页面会随着页面的放大缩小而随之发生变化&#xff0c;这种自适应的页面布局在大屏幕、小屏幕、不同的浏览器设备上都应该呈现出与设计匹配的…

【STM32MP157应用编程】4.串口接收、发送数据

目录 串口文件 指令操作串口 程序操作串口 程序说明 程序代码 4_ChuanKou_2.c 启动交叉编译工具 编译 拷贝到开发板 测试 串口文件 在/dev目录下&#xff0c;存放了串口的文件。 文件名对应的串口ttySTM0CH340ttySTM1com2&#xff08;公头&#xff09;ttySTM2com1&a…

java版云HIS系统源码 微服务架构支持VUE

云his系统源码 一个好的HIS系统&#xff0c;要具有开放性&#xff0c;便于扩展升级&#xff0c;增加新的功能模块&#xff0c;支撑好医院的业务的拓展&#xff0c;而且可以反过来给医院赋能&#xff0c;最终向更多的患者提供更好地服务。 私信了解更多&#xff01; 本套基于…

【C语言】结构体和共用体

目录一、结构体&#xff08;一&#xff09;结构体声明&#xff08;二&#xff09;结构体变量定义&#xff08;三&#xff09;结构体变量的初始化&#xff08;四&#xff09;结构体的引用&#xff08;五&#xff09;结构体数组二、共用体&#xff08;一&#xff09;共用体定义&a…

全球商城库存系统架构设计与实践

业务背景 商城原库存系统耦合在商品系统&#xff0c;考虑到相关业务逻辑复杂度越来越高&#xff0c;库存做了服务拆分&#xff0c;在可售库存管理的基础上新增了实物库存管理、秒杀库存、物流时效 、发货限制、分仓管理等功能&#xff0c;满足了商城库存相关业务需求。 系统架构…

GitLab 存储型XSS漏洞 (CVE-2023-0050)

漏洞描述 GitLab 是由GitLab公司开发的、基于Git的集成软件开发平台。kroki是一款集成在GitLab的基于文本的图表描述自动转为图片的开源工具&#xff0c;在GitLab 13.7引入。 由于Kroki中lib/banzai/filter/kroki_filter.rb对接收的image_src过滤不严&#xff0c;具有AsciiDo…

SpringBoot 整合 clickhouse和mysql 手把手教程全网最详细

最近做一个项目 需要 整合mysql clickhouse 多数据源 后台用的是ruoyi框架 1. 首先pom引入相关依赖 <!--JDBC-clickhouse数据库--><dependency><groupId>com.clickhouse</groupId><artifactId>clickhouse-jdbc</artifactId><version&…

Homekit智能家居产品---智能吸顶灯

买灯要看什么因素 好灯具的灯光可以说是家居的“魔术师”&#xff0c;除了实用的照明功能外&#xff0c;对细节的把控也非常到位。那么该如何选到一款各方面合适的灯呢&#xff1f; 照度 可以简单理解为清晰度&#xff0c;复杂点套公式来说照度光通量&#xff08;亮度&#x…

5款小巧好用的电脑软件,让你的工作生活更加高效!

不得不说良心好软件让大家好评连连&#xff0c;爱不释手&#xff0c;不像某些软件自带广告弹窗。这期就由我给大家安利几款电脑中的得力助手&#xff0c;看看你都用过几个&#xff1f; 1.桌面管理神器——Coodesker Coodesker是一款免费小巧、无广告&#xff0c;功能简单的桌…