react-router原理

news/2025/1/16 4:58:30/

前端路由的原理

自己来监听URL的改变,改变url,渲染不同的组件(页面),但是页面不要进行强制刷新(a元素不行)。

  • hash模式,localhost:3000/#/abc
    • 优势就是兼容性更好,在老版IE中都可以运行
    • 缺点是有一个#,显得不像一个真实的路径
  • 通过HTML5中的history修改URL

1. URL的hash

原理:通过监听hashchange变化

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><div id="app"><a href="#/home">首页</a><a href="#/about">关于</a><div class="router-view"></div></div><script>// 获取router-view的DOMconst routerViewEl = document.getElementsByClassName("router-view")[0];// 监听URL的改变window.addEventListener("hashchange", () => {switch (location.hash) {case "#/home":routerViewEl.innerHTML = "首页";break;case "#/about":routerViewEl.innerHTML = "关于";break;default:routerViewEl.innerHTML = "";}});</script></body>
</html>

2. HTML5的history

history接口是HTML5新增的,常见方法和事件如下:

  • pushState: 使用新的路径
  • replaceState: 替换原来的路径
  • popstate事件
  • go: 向前或向后改变路径
  • forward: 向前改变路径
  • back: 向后改变路径

其中,pushState、replaceState、go、forward、back改变URL而不刷新页面,参考:https://blog.csdn.net/pj598707063/article/details/90720767

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><div id="app"><a href="/home">首页</a><a href="/about">关于</a><div class="router-view"></div></div><script>// 1.获取router-view的DOMconst routerViewEl = document.getElementsByClassName("router-view")[0];// 获取所有的a元素, 自己来监听a元素的改变const aEls = document.getElementsByTagName("a");for (let el of aEls) {el.addEventListener("click", (e) => {e.preventDefault();const href = el.getAttribute("href");history.pushState({}, "", href);urlChange();});}// 执行返回操作时, 依然来到urlChangewindow.addEventListener("popstate", urlChange);// 监听URL的改变function urlChange() {switch (location.pathname) {case "/home":routerViewEl.innerHTML = "首页";break;case "/about":routerViewEl.innerHTML = "关于";break;default:routerViewEl.innerHTML = "";}}</script></body>
</html>

react-router

react-router的版本4开始,路由不再集中在一个包进行管理了,而是进行了分包:

  • react-router是router的核心代码
  • react-router-dom是用于浏览器的
  • react-router-native是用于RN应用的

提示:安装react-router-dom会自动安装react-router

1. react-router基础

在这里插入图片描述

2. NavLink

在这里插入图片描述

NavLink是对Link的一个封装,支持更多属性,例如exact、activeStyle、activeClassName(这个属性的默认值为active)等

3. 动态路由

<NavLink to={`/detail/${id}`} activeClassName="link-active">详情</NavLink>
// const match = this.props.match;
// console.log(match.params);<NavLink to={`/detail2?name=xiaoming&age=18`} activeClassName="link-active">详情2</NavLink>
// <h2>Detail2: {this.props.location.search}</h2>
<NavLink to={{pathname: "/detail3",search: "name=abc",state: info}} activeClassName="link-active">详情3
</NavLink>
// to后面的对象将被保留到this.props.location中
// <h2>Detail3: {this.props.location.state.name}</h2>

4. redirect

import React, { PureComponent } from 'react'
import { Redirect } from 'react-router-dom';export default class User extends PureComponent {constructor(props) {super(props);this.state = {isLogin: true}}render() {return this.state.isLogin ? (<div><h2>User</h2><h2>用户名: coderwhy</h2></div>): <Redirect to="/login"/>}
}

5. 嵌套路由(19-45分)

在这里插入图片描述
对于嵌套路由,为了避免子路由里重父组件上的路径,可以通过basename处理,参考https://v5.reactrouter.com/web/api/BrowserRouter/basename-string

在这里插入图片描述

6. 手动路由跳转(19-59)

// App.jsx
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:id" component={User} />

因为About组件是在Route的component里渲染的,所以Route可以给About组件灌入很多属性,包括history、match等

// About.jsx
export default class About extends PureComponent {render() {console.log(this.props.route);const branch = matchRoutes(this.props.route.routes, "/about");console.log(branch);return (<div><NavLink exact to="/about" activeClassName="about-active">企业历史</NavLink><NavLink exact to="/about/culture" activeClassName="about-active">企业文化</NavLink><NavLink exact to="/about/contact" activeClassName="about-active">联系我们</NavLink><button onClick={e => this.jumpToJoin()}>加入我们</button><Switch><Route exact path="/about" component={AboutHisotry}/><Route path="/about/culture" component={AboutCulture}/><Route path="/about/contact" component={AboutContact}/><Route path="/about/join" component={AboutJoin}/></Switch></div>)}jumpToJoin() {// console.log(this.props.history);// console.log(this.props.location);// console.log(this.props.match);this.props.history.push("/about/join");}
}
withRouter (19 - 1:21)

源码阅读:react-router-dom再调用了react-router
在这里插入图片描述

7. 路由统一管理react-router-config

对于上面的嵌套路由显得太零散,因此需要对路径进行统一管理。

// router.js
import Home from '../pages/home';
import About, { AboutHisotry, AboutCulture, AboutContact, AboutJoin } from '../pages/about';
import Profile from '../pages/profile';
import User from '../pages/user';const routes = [{path: "/",exact: true,component: Home},{path: "/about",component: About,// 子路由routes: [{path: "/about",exact: true,component: AboutHisotry},{path: "/about/culture",component: AboutCulture},{path: "/about/contact",component: AboutContact},{path: "/about/join",component: AboutJoin},]},{path: "/profile",component: Profile},{path: "/user",component: User}
]
export default routes;
// App.js
import { renderRoutes } from 'react-router-config';
import routes from './router';
render() {return (<div>{renderRoutes(routes)}</div>)
}
// About.js
import { renderRoutes } from 'react-router-config';
render() {return (<div><NavLink exact to="/about" activeClassName="about-active">企业历史</NavLink><NavLink exact to="/about/culture" activeClassName="about-active">企业文化</NavLink><NavLink exact to="/about/contact" activeClassName="about-active">联系我们</NavLink><button onClick={e => this.jumpToJoin()}>加入我们</button>{/* <Switch><Route exact path="/about" component={AboutHisotry}/><Route path="/about/culture" component={AboutCulture}/><Route path="/about/contact" component={AboutContact}/><Route path="/about/join" component={AboutJoin}/></Switch> */}// 因为父组件是通过renderRoutes渲染的,所以能够拿到this.props.route{renderRoutes(this.props.route.routes)}</div>)}

react-router-config

参考链接:react-router


http://www.ppmy.cn/news/43044.html

相关文章

【hello Linux】Linux软件管理器yum

目录 1.Linux软件管理器yum 1.1 关于lrzsz 1.2 使用yum时的注意事项 1.3 查看软件包&#xff1a;yum list 1.4 安装软件&#xff1a;yum install 1.5 卸载软件&#xff1a;yum remove 1.6 更新yum源 1.7 实战项目 Linux&#x1f337; 1.Linux软件管理器yum 在windows系统下有应…

技术创业者必读:从验证想法到技术产品商业化的全方位解析

导语 | 技术创业之路往往充满着挑战和不确定性&#xff0c;对于初入创业领域的人来说&#xff0c;如何验证自己的创业想法是否有空间、如何选择靠谱的投资人、如何将技术产品商业化等问题都需要认真思考和解决。在「TVP 技术夜未眠」第六期直播中&#xff0c;正马软件 CTO、腾讯…

ChatGPT风口下的中外“狂飙”,一文看懂微软、谷歌、百度、腾讯、华为、字节跳动们在做什么?

毫无疑问&#xff0c;ChatGPT正成为搅动市场情绪的buzzword。 历史经历过无线电&#xff0c;半导体&#xff0c;计算机&#xff0c;移动通讯&#xff0c;互联网&#xff0c;移动互联网&#xff0c;社交媒体&#xff0c;云计算等多个时代&#xff0c;产业界也一直在寻找Next Bi…

Java开发 - MySQL主从复制初体验

前言 前面已经学到了很多知识&#xff0c;大部分也都是偏向于应用方面&#xff0c;在应用实战这条路上&#xff0c;博主一直觉得只有实战才是学习中最快的方式。今天带来主从复制给大家&#xff0c;在刚刚开始动手写的时候&#xff0c;才想到似乎忽略了一些重要的东西&#xf…

Ubuntu搭建web站点并发布公网访问【内网穿透】

文章目录前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子域名前言 网&#xff1a;我们通常说的是互联网&#xff1b;站…

蓝牙设备如何自定义UUID

如何自定义UUID 所有 BLE 自定义服务和特性必须使用 128 位 UUID 来识别&#xff0c;并且要确保基本 UUID 与 BLE 定义的基本 UUID&#xff08;00000000-0000-1000-8000-00805F9B34FB&#xff09;不一样。基本 UUID 是一个 128 位的数值&#xff0c;根据该值可定义标准UUID&am…

ACM8629 立体声50W/100W单声道I2S数字输入D类音频功放IC

概述 ACM8629 一款高度集成、高效率的双通道数字输入功放。供电电压范围在4.5V-26.4V,数字接口电源支持3.3V 。在4 欧负载&#xff0c;BTL模式下输出功率可以到250W1%THDN&#xff0c;在2欧负载&#xff0c;PBTL模式下单通道可以输出1100W 1%THDN. ACM8629采用新型PWM脉宽调制架…

C++标准库--IO库(Primer C++ 第五版 · 阅读笔记)

C标准库--IO库(Primer C 第五版 阅读笔记&#xff09;第8章 IO库8.1、IO类8.2、文件输入输出8.3、string流总结&#xff1a;第8章 IO库 8.1、IO类 为了支持这些不同种类的IO处理操作&#xff0c;在istream和ostream之外&#xff0c;标准库还定义了其他一些IO类型。 如下图分…