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

【React-Router】路由传参,路由嵌套,手动导航,路由文件配置

文章目录

  • React-Router
      • URL的hash
      • HTML5的History
    • Router的基本使用
      • 路由映射配置
      • 路由的嵌套
      • 路由配置和跳转
        • Link和NavLink:
        • 手动路由的跳转
        • 路由参数传递
      • Navigate导航
      • Not Found页面配置
    • 路由的配置文件

React-Router

前端路由是如何做到URL和内容进行映射呢?怎么原生的监听URL的改变。

URL的hash

URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新;
hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径。
hashchange事件触发时,事件对象会有hash改变前的URL(oldURL)和hash改变后的URL(newURL)两个属性:

window.addEventListener('hashchange',function(e) { console.log(e.oldURL); console.log(e.newURL) },false);

HTML5的History

◼ history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面:
 replaceState:替换原来的路径;
 pushState:使用新的路径;
 popState:路径的回退;
 go:向前或向后改变路径;
 forward:向前改变路径;
 back:向后改变路径;
popstate 事件是通过 window.addEventListener('popstate') 进行注册的。但触发条件需要满足下面两点:

点击浏览器的【前进】【后退】按钮,或者调用 history 对象的 back、forward、go 方法
之前调用过 history 对象的 replaceState 或 pushState 方法

Router的基本使用

安装React Router:

npm install react-router-do

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

BrowserRouter或HashRouter

​  Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;

​  BrowserRouter使用history模式;

​  HashRouter使用hash模式;

-src

—index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';
import { HashRouter,BrowserRouter } from 'react-router-dom';const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(// <React.StrictMode><HashRouter><Provider store={store}><App /></Provider></HashRouter>// </React.StrictMode>
);

路由映射配置

Routes:包裹所有的Route,在其中匹配一个路由

​  Router5.x使用的是Switch组件

Route:Route用于路径的匹配;

​  path属性:用于设置匹配到的路径;

​  element属性:设置匹配到路径后,渲染的组件;

​ ✓ Router5.x使用的是component属性

​  exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;

​ ✓ Router6.x不再支持该属性

-src

—App.jsx

import {Routes,Route
} from "react-router-dom";export class App extends PureComponent {render() {<Routes><Route path="/home" element={<Home />}></Routes>}}

路由的嵌套

在开发中,路由之间是存在嵌套关系的。

◼ 组件用于在父路由元素中作为子路由的占位元素。

-src

—pages

-------App.jsx

			<Routes><Route path="/home" element={<Home />}><Route path="/home/homeChild" element={<HomeChild />}></Route></Route></Routes>

-src

—pages

-------Home.jsx

子路由的出口

组件用于在父路由元素中作为子路由的占位元素。

这样HomeChild组件就会被渲染到Home组件的占位元素的位置

		export class Home extends PureComponent {render() {<div><h2>Home Page</h2><div>{/* 占位组件 */}<Outlet /></div></div>}}

路由配置和跳转

Link和NavLink:

​  通常路径的跳转是使用Link组件,最终会被渲染成a元素;

​  NavLink是在Link基础之上增加了一些样式属性,默认叫active的className,通过配置css可以让选中的标签展现active类名下的样式;

​  to属性:Link中最重要的属性,用于设置跳转到的路径;

-src

—App.jsx

import {Routes,Route
} from "react-router-dom";
import './style.css'export class App extends PureComponent {render() {<div><nav><Link to="/home">首页</Link><NavLink to="/home">首页</NavLink></nav><Routes><Route path="/home" element={<Home />}></Routes></div>}}

-src

—style.css

nav .active {color: red;font-size: 18px;
}

手动路由的跳转

实际上我们也可以通过JavaScript代码进行跳转。

​  我们知道Navigate组件是可以进行路由的跳转的,但是依然是组件的方式。

​  如果我们希望通过JavaScript代码逻辑进行跳转(比如点击了一个button),那么就需要获取到navigate对象

在Router6.x版本之后,代码类的API都迁移到了hooks的写法:

​  如果我们希望进行代码跳转,需要通过useNavigate的Hook获取到navigate对象进行操作;

例子:

import {useNavigate,
} from "react-router-dom";export function RouterHook() {const navigate = useNavigate()return(<div><button onClick={e => navigate('/home')}>去home</button></div>)
}

​  那么如果是一个函数式组件,我们可以直接调用,但是如果是一个类组件呢?

​ 类组件我们可以使用一个高阶组件包裹,在返回的组件的props中写入react-router-dom的方法,这里封装了useLocation, useNavigate, useParams, useSearchParams四个钩子

useParamsuseSearchParams钩子:用来接收路由传参

useLocation钩子:监听路由的地址

useNavigate钩子:实现手动路由跳转

案例:

​ -src

​ —hoc

​ -------withRouter.js

import { useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom";function withRouter(WrapperComponent) {return function (props) {// 1.导航const navigate = useNavigate()// 2.动态路由的参数: /detail/:idconst params = useParams()// 3.查询字符串的参数: /user?name=why&age=18const [searchParams] = useSearchParams()const query = Object.fromEntries(searchParams)// 4.路由地址const location = useLocation()const router = { navigate, params, location, query }return (<WrapperComponent{...props}router={router}></WrapperComponent>);};
}export default withRouter

再到类组件中使用withRouter高阶组件包裹需要使用router hook的组件上

import withRouter from "../hoc/withRouter";export class Home extends PureComponent {....
}export default withRouter(Home);

路由参数传递

传递参数有二种方式:

​  动态路由的方式;

​  search传递参数;

动态路由的概念指的是路由中的路径并不会固定:

​  比如/detail的path对应一个组件Detail;

​  如果我们将path在Route匹配时写成/detail/:id,那么 /detail/abc、/detail/123都可以匹配到该Route,并且进行显示;

​  这个匹配规则,我们就称之为动态路由;

​  通常情况下,使用动态路由可以为路由传递参数。

路由传递参数

import {Link,Routes,Route,
} from "react-router-dom";export function App(props) { return (<div><Link to="/home/detail/123">给detail页面传参123</Link><Routes><Route path="/home/detail/:id" element={<Detail />}></Route></Routes></div>)
}                          

在组件中接收参数

import React, { PureComponent } from 'react'
import { withRouter } from '../hoc'export class Detail extends PureComponent {render() {const { router } = this.propsconst { params } = routerreturn (<div><h1>Detail Page</h1><h2>id: {params.id}</h2></div>)}
}export default withRouter(Detail)

search传递参数

给Contexta组件路由传参

import {Link,Routes,Route,
} from "react-router-dom";export function App(props) { return (<div><Link to="/home/context?age=18&name=顽皮宝">给contexta页面传参</Link><Routes><Route path="/home/context" element={<Contexta />}></Route></Routes></div>)
}  

在组件中接收参数

import React, { PureComponent } from 'react'
import { withRouter } from '../hoc'export class Contexta extends PureComponent {render() {const { router } = this.propsconst { query } = routerreturn (<div><h1>User: {query.name}-{query.age}</h1></div>)}
}export default withRouter(Contexta)

Navigate导航

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

j例子:在匹配到’/'的时候,直接跳转到/home页面

<Route path="/" element={<Navigate to="/home" />}></Route>

Not Found页面配置

如果用户随意输入一个地址,该地址无法匹配,那么在路由匹配的位置将什么内容都不显示。

很多时候,我们希望在这种情况下,让用户看到一个Not Found的页面。

​  开发一个Not Found页面;

​  配置对应的Route,并且设置path为*即可;

<Route path="*" element={<NotFound />}></Route>

路由的配置文件

目前我们所有的路由定义都是直接使用Route组件,并且添加属性来完成的。

但是这样的方式会让路由变得非常混乱,我们希望将所有的路由配置放到一个地方进行集中管理:

​  在早期的时候,Router并且没有提供相关的API,我们需要借助于react-router-config完成;

​  在Router6.x中,为我们提供了useRoutes API可以完成相关的配置;

如果我们对某些组件进行了异步加载(懒加载),那么需要使用Suspense进行包裹

​ -src

​ —router

​ -------index.js

import Home from '../pages/Home'
import HomeRecommend from "../pages/HomeRecommend"// import About from "../pages/About"
// import Login from "../pages/Login"
import { Navigate } from 'react-router-dom'
import React from 'react'// 懒加载
const About = React.lazy(() => import("../pages/About"))
const Login = React.lazy(() => import("../pages/Login"))const routes = [{path: "/",element: <Navigate to="/home"/>},{path: "/home",element: <Home/>,children: [{path: "/home/recommend",element: <HomeRecommend/>},]},{path: "/about",element: <About/>},{path: "/login",element: <Login/>},
]export default routes

​ -src

​ —App.jsx

import React from 'react'
import { Link,  useRoutes } from 'react-router-dom'
import routes from './router'export function App(props) {return (<div className='app'><div className='nav'><Link to="/home">首页</Link><Link to="/login">登录</Link></div><div className='content'>{useRoutes(routes)}</div></div>)
}export default App
http://www.lryc.cn/news/956.html

相关文章:

  • 面向对象分析与设计(OOAD)
  • 数据库调优
  • OpenStack云平台搭建(3) | 部署Glance
  • 软件评测师考试总结
  • 小白系列Vite-Vue3-TypeScript:009-屏幕适配
  • 查找企业微信聊天记录,会话存档有多重要
  • C语言经典编程题100例(1-20)
  • 小白系列Vite-Vue3-TypeScript:008-安装配置mock
  • OnGUI Box 控件||Unity 3D OnGUI 常用控件
  • shiro721——CVE-2019-12422
  • 爬虫JS逆向思路 - - 扣JS(data解密)
  • Android 进阶——Framework 核心之Binder 相关预备理论(一)
  • 【23种设计模式】结构型模式详细介绍
  • 接口自动化实战-postman
  • 前端跨域方案简单总结
  • 【HTML】HTML 表格 ② ( 表头单元格标签 | 表格标题标签 )
  • 常用的辅助类2(StringBuilder、StringBuffer、处理时间相关的类、对象比较器)
  • anaconda下pytorchCPU GUP安装及问题记录
  • 香港中文大学MISC Lab GNN团队: 异质图神经网络研究进展从谱的角度看待(图)对比学习(图自监督学习)
  • C#开发的OpenRA的Enumerable.Concat方法应用
  • 前端知识点总结(自参)
  • [ 靶场环境片 ] kali-linux采用Docker 搭建 pikachu(特别详细)
  • 阿里6面,成功唬住面试官拿了27K,软件测试面试也没有传说中那么难吧....
  • 为什么静默安装未经过数字签名的驱动是不可行的?
  • Caused by: java.sql.SQLException: ORA-28040: 没有匹配的验证协议
  • Dubbo3简单使用
  • Redis未授权漏洞蜜罐模拟与捕获分析
  • Spring Security Oauth2.0认证授权
  • 安卓小游戏:贪吃蛇
  • CUDA中的图内存节点