当前位置: 首页 > news >正文

Redux (八) 路由React-router、嵌套路由、路由传参、路由懒加载

文章目录

  • 一、React-Router的基本使用
    • 1. 安装及基本使用(路由映射配置)
    • 2. 路由跳转Link与NavLink
    • 3. Navigate导航
    • 4. 处理路径不存在的情况
  • 二、嵌套路由
  • 三、手动跳转 (类似编程式路由导航)
    • 1. 函数式组件
    • 2. 类组件实现手动跳转
  • 四、路由传参
    • 1. 路径设置占位符(params)
    • 2. search传递参数
  • 五、路由配置到单独的文件中(useRoutes)
  • 六、路由懒加载

一、React-Router的基本使用

1. 安装及基本使用(路由映射配置)

安装:

npm install react-router-dom

react-router最主要的时提供了一系列重要的组件,

(1) 设置路由模式
路由有两种模式:hash和history,对应react-router里的两个组件HashRouterBrowserRouter

HashRouter : 设置应用的路由采用hash模式

import { HashRouter } from 'react-router-dom';
root.render(<HashRouter><App /></HashRouter>
);

BrowserRouter: 设置应用的路由采用history模式

import { HashRouter, BrowserRouter } from 'react-router-dom';
root.render(<BrowserRouter><App /></BrowserRouter>
);

hash模式地址有#,history模式没有,开发更习惯用hash模式。

(2) 路由的映射配置
Routes组件:包裹所有的Route
Route: 用于设置路径与组件的对应关系,有两个属性:
path属性: 用于设置路径
element属性: 设置路径对应的组件.

import { Route, Routes } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
export class App extends PureComponent {render () {return (<div><div className="header"><h2>Header</h2></div><hr /><div className='content'><Routes>{/* /home路径对应Home组件 */}<Route path='/home' element={<Home />} /><Route path='/about' element={<About />} /></Routes></div><hr /><div className="footer"><h2>Footer</h2></div></div>)}
}

在这里插入图片描述

2. 路由跳转Link与NavLink

LinkNavLink有点像vue里的router-link,to属性指定跳转的路径。最终都会被渲染称a元素。
两者的区别是:NavLink在被选中时,会自动加上active的类名。可以借此设置一些样式
在这里插入图片描述
点击不同的链接:

在这里插入图片描述

3. Navigate导航

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

比如用户在登录页,当点击登录按钮时,自动跳转到home页面。

import { Navigate } from 'react-router-dom'export class Login extends PureComponent {constructor() {super()this.state = {isLogin: false}}login () {this.setState({ isLogin: true })}render () {const { isLogin } = this.statereturn (<div><h3>登录界面</h3>{/* isLogin为true,则跳转到home页面,否则显示按钮 */}{isLogin ? <Navigate to='/home' /> : <button onClick={e => this.login()}>登录</button>}</div>)}
}
export default Login

还有路由重定向问题;当路径为/时,需要重定向到别的页面,比如重定向到首页。

   <div className='content'><Routes>{/* 重定向方式一: */}<Route path='/' element={<Navigate to='/login' />} />{/* 重定向方式二: */}<Route path='/' element={<Home />} /><Route path='/home' element={<Home />} /><Route path='/about' element={<About />} /><Route path='/login' element={<Login />} /></Routes></div>

4. 处理路径不存在的情况

随便输入一个不存在的网址:

http://localhost:3000/#/abc

针对这种情况,一般会单独写一个NotFound的页面,提示用户页面不存在。
我们通过 设置路径为通配符*来映射到NotFound页面。

     <div className='content'><Routes>{/* 重定向方式一: */}<Route path='/' element={<Navigate to='/login' />} />{/* 重定向方式二: */}<Route path='/' element={<Home />} /><Route path='/home' element={<Home />} /><Route path='/about' element={<About />} /><Route path='/login' element={<Login />} />{/* 路径一路匹配,匹配不到,说明路径不存在时,最后通过通配符*,跳转到NotFound页面 */}<Route path='/*' element={<NotFound />} /></Routes></div>

二、嵌套路由

在这里插入图片描述
在content里显示Home组件的内容,Home组件里又显示推荐、排行等子组件。
现在要实现点击推荐、排行,显示对应的组件。

App.jsx

<div className='content'><Routes>{/* 重定向 */}<Route path='/' element={<Navigate to='/home' />} /><Route path='/home' element={<Home />} >{/* 跳转到首页时,自动重定向到推荐页面 */}<Route path='/home' element={<Navigate to='/home/recommend' />} />{/* 嵌套路由 */}<Route path='/home/recommend' element={<HomeRecommend />} /><Route path='/home/rank' element={<HomeRanking />} /><Route path='/home/songmenu' element={<HomeSongMenu />} /></Route><Route path='/about' element={<About />} /><Routes/>
<div/>

嵌套路由就是在Route的双标签里,写子组件的路由Route

由于是Home页面内嵌套显示其他页面,所以Home.js:

return (<div><h3>Home</h3><Link to='/home/recommend'>推荐</Link><Link to='/home/rank'>排行</Link><button>歌曲目录</button>{/* 占位,推荐,排行,歌曲目录的子组件在这儿展示 */}<Outlet /></div>
)
}

Outlet用于在父路由组件中子路由的占位,

三、手动跳转 (类似编程式路由导航)

react-router-dom提供了函数useNavigate,调用它会返回一个函数,执行该函数并将跳转路径传入就会实现跳转。但是useNavigate这个hook只能在函数式组件中使用。

1. 函数式组件

比如组件About

//App.jsx,在App组件中,其路由嵌套关系为:<Route path='/about' element={<About />} ><Route path='/about/singers' element={<Singers />} /><Route path='/about/platform' element={<Platform/>} /></Route>//About.jsx 点击关于歌手按钮,实现页面跳转。
import React from 'react'
import { useNavigate, Outlet } from 'react-router-dom'
function About (props) {const nav = useNavigate()  //调用hookfunction navigateTo (path) {nav(path)}return (<div><h2>About</h2><button>关于平台</button><button onClick={e => navigateTo('/about/singers')}>关于歌手</button>{/* 占位符,子组件 Singers的内容会展示在这里 */}<Outlet /></div>)
}export default About

2. 类组件实现手动跳转

类组件要实现手动跳转,需要通过高阶组件给其注入useNavigate()返回的函数。

// with_router.js
import { useNavigate } from 'react-router-dom'
function withRouter (OriginComponent) {
// useNavigate 只有高阶组件在用,所以只能返回一个函数组件return function (props) {const nav = useNavigate()// nav放进对象里,注入到组件的props里return <OriginComponent {...props} router={{ nav }} />}
}
export default withRouter

组件内:

// Home组件,页面的图片在上一节嵌套路由出现过
export class Home extends PureComponent {navigateTo (path) {this.props.router.nav(path)}render () {return (<div><h3>Home</h3><Link to='/home/recommend'>推荐</Link><Link to='/home/rank'>排行</Link><button onClick={e => this.navigateTo('/home/songmenu')}>歌曲目录</button>{/* 占位 */}<Outlet /></div>)}
}
export default withRouter(Home)

四、路由传参

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

设置占位:

在这里插入图片描述
  Detail组件接收这种通过占位符传递的参数,需要用到一个hook函数useParams(),但它也只能在函数组件中使用。所以我们可以在高阶组件中使用useParams(),将得到的参数注入到Deatilprops中。

还是上面封装的那个高阶组件with_router.js

import { useNavigate, useParams} from 'react-router-dom'
function withRouter (OriginComponent) {return function (props) {// 1. 导航const nav = useNavigate()// 2. 动态路由参数--paramsconst params = useParams()const router = { nav, params, }return <OriginComponent {...props} router={router} />}
}
export default withRouter

Detail.jsx

import React, { PureComponent } from 'react'
import withRouter from '../hoc/with_router'
export class Detail extends PureComponent {render () {const { params } = this.props.routerreturn (<div><h2>Detail</h2><h3>获取到的id是:{params.id}</h3></div>)}
}
export default withRouter(Detail)

在这里插入图片描述

2. search传递参数

参数通过?拼接到url中(类似query参数)。
在这里插入图片描述
与上边类似,可以借助useSearchParams()获取到路径里拼接的参数。由于这也是一个hook,所以我们也在高阶组件里调用useSearchParams(),得到参数,注入到组件的props中。

with_router.js

import { useNavigate, useParams, useSearchParams } from 'react-router-dom'function withRouter (OriginComponent) {return function (props) {// 1. 导航const nav = useNavigate()// 2. 动态路由参数--paramsconst params = useParams()// 3. 字符串参数(query)---const [searchParams] = useSearchParams()// console.log(searchParams.get('name'));const query = Object.fromEntries(searchParams.entries())const router = { nav, params, query }return <OriginComponent {...props} router={router} />}
}
export default withRouter

此处再补充一个hookuseLocation,也可以获取到字符串拼接的值

    const location = useLocation()console.log('location', location);

在这里插入图片描述

Login.jsx
组件接收数据:

export class Login extends PureComponent {render () {const { query } = this.props.routerreturn (<div><h3>登录界面</h3><h4>query参数 --{query.name}--{query.age}</h4></div>)}
}
export default withRouter(Login)

在这里插入图片描述

五、路由配置到单独的文件中(useRoutes)

总在App.jsx里写,不直观且代码较为复杂;
在这里插入图片描述
因此将路由的映射关系单独配置到到文件router/idnex.js

// 写了几个代表性的
const routes = [{path: './',element: <Navigate to='/home' /> //重定向},{path: '/home',element: <Home />,children: [{path: '/home',element: <Navigate to='/home/recommend' />},{path: '/home/recommend',element: <HomeRecommend />},{path: '/home/rank',element: <HomeRanking />}]},{path: '/detail/:id',element: <Detail />},
... {path: '*',element: <NotFound />},
]export default routes

  在App组件中,用到useRoutes来将这些routes转换成原来的Routes这样的标签元素。但useRoutes是个hook,因此采用高阶组件将其注入到App组件中:

function withRouter (OriginComponent) {return function (props) {const routeEle = useRoutes(routes)return <OriginComponent {...props} routeEle={routeEle} />}
}

在这里插入图片描述

六、路由懒加载

(1)将路径改为懒加载
在这里插入图片描述
 改为懒加载的路径,会单独打到一个文件里,当用的时候再去加载这个文件。否则会全都打包到一个文件里。

(2)包裹Suspense 标签

import React, { Suspense } from 'react';
...
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<HashRouter>{/* 包裹Suspense 标签,当路由加载还未显示在页面上时,显示fallback里的内容 */}<Suspense fallback={<h3>路由懒加载中!!</h3>}><App /></Suspense></HashRouter>
);

http://www.mrgr.cn/news/54885.html

相关文章:

  • Spring Boot配置文件不识别变量的解决方案
  • 极氪汽车困局:营销频繁车、产品力不足
  • 第十四届单片机嵌入式蓝桥杯
  • Qt中使用线程之QThread
  • 碰到这个问题请更新或重新安装fastapi版本
  • 代码随想录算法训练营第三十一天|56. 合并区间、738.单调递增的数字
  • 【Android】浅析OkHttp(1)
  • MySQL-29.事务-四大特性
  • web3学习-区块链基础知识
  • 图文深入介绍oracle资源管理(续)
  • 10.20学习
  • Linux基本指令一眼看懂(简洁表示)
  • C语言实践中的补充知识 Ⅱ
  • 【AIGC视频生成】视频扩散模型(综述+最新进展)
  • Python第五节 迷宫王国的奇幻旅程
  • TypeScript中 interface接口 type关键字 enum枚举类型
  • Guava防击穿回源-异步防击穿
  • nginx的配置
  • 电子政务的类型
  • SHELL函数之的使用
  • 【论文翻译】ICLR 2018 | DCRNN:扩散卷积递归神经网络:数据驱动的交通预测
  • Python练习3
  • 空间复杂度
  • Java程序OutOfMemoryError分析与heap dump
  • Chromium127编译指南 Windows篇 - depot_tools工具的安装与设置(二)
  • 三种容器 std::vector、std::map、std::unordered_set 的对比分析