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

【React】react-router-dom中的HashRouter和BrowserRouter实现原理

1. 前言

        在之前整理BOM的五个对象时,提到:

  • location.hash发生改变后,会触发hashchange事件,且history栈中会增加一条记录,但页面不会重新加载——实现HashRouter的关键
  • history.pushState(state, '', URL)执行后,history栈中会增加一条记录,但页面不会重新加载,回退(history.back()或history.go(-1))会触发popstate事件,location.pathname发生改变——实现BrowserRouter的关键

        本篇通过举例方式详细描述实现的过程。

2. HashRouter的原理
2.1 原理要点
  • 通过<a>元素href属性修改URL的hash值(或location.hash='#/xxx'修改,或前进后退修改);
  • location.hash发生改变,页面不会重新加载;
  • location.hash发生改变,URL也会改变(hash是URL的一部分),新URL被推入history栈中;
  • location.hash发生改变,会触发window的hashchange事件;
  • 通过给window.onhashchange绑定事件处理函数,监听hash变化,根据hash值选择渲染的组件。

注:根据hash值变化渲染组件,不会影响hash原有作为锚点的功能(锚点功能:根据#后面字符串滚动到对应id的元素 )

2.2 示例源码
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Hash Router</title></head><body><a href="#/user">Go user</a><a href="#/info">Go info</a><div id="root"></div><!-- <div style="height: 600px;"></div><div id="/info"></div> --><script>let root = document.getElementById('root');window.onhashchange = function(event) {if(window.location.hash === '#/user') {root.innerHTML = `<label>用户名:<input value="小明" placeholder="user name"/></label>`;} else {root.innerHTML = `<label>年龄:13岁</label>`;}}</script></body>
</html>
3. BrowserRouter的原理
3.1 原理要点
  • window不支持onpushstate事件,需要为window构造onpushstate事件,并绑定事件处理函数,重写history.pushState,保证执行history.pushState就会触发onpushstate事件;
  • 可以为菜单项绑定click事件处理函数,执行重写的history.pushState(state,title,url)修改URL;
  • 执行重写的history.pushState,页面不会重新加载,但location.pathname发生改变,并触发window的onpushstate事件;
  • 通过window.onpushstate的事件处理函数,监听pathname变化,根据pathname值选择渲染的组件;
  • 前进和后退会改变URL,页面不会重新加载,location.pathname发生改变,并触发window的onpopstate事件;
  • 通过window.onpopstate绑定的事件处理函数,监听pathname变化,根据pathname值选择渲染的组件。
3.2 示例源码
<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Hash Router</title></head><body><div id="root"></div><script>let root = document.getElementById('root');window.onpushstate = function(state, title, url) {console.dir({type: 'onpushstate', state, pathname: url});render(url);}// 修改history.pushState方法,将window.onpushstate事件绑入bindPushstate(window.history);function bindPushstate(history) {let pushState = history.pushState;history.pushState = function(state, title, url) {if(typeof window.onpushstate === 'function') {window.onpushstate(state, title, url);}return pushState.apply(history, arguments);}}            window.onpopstate = function(event) {const pathname = window.location.pathname;console.dir({type: event.type, state: event.state,pathname});render(pathname);}function render(pathname) {if(pathname === '/user') {root.innerHTML = `<label>用户名:<input value="小明" placeholder="user name"/></label>`;} else if(pathname === '/info') {root.innerHTML = `<label>年龄:13岁</label>`;} else {root.innerHTML = `<label>需要填写个人信息</label>`;}}setTimeout(() => {window.history.pushState({ page: 1 }, 'user', '/user');}, 2000);setTimeout(() => {window.history.pushState({ page: 2 }, 'info', '/info');}, 4000);setTimeout(() => {window.history.pushState({ page: 3 }, 'help', '/help');}, 6000);</script></body>
</html>
4. 总结

        再牛的建筑都离不开一块一块砖瓦,学到很多高大上的框架和上层API时,再回过头来看基础,会更加深对框架和上层API的理解。

注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~  

相关文章:

【React】react-router-dom中的HashRouter和BrowserRouter实现原理

1. 前言 在之前整理BOM的五个对象时&#xff0c;提到&#xff1a; location.hash发生改变后&#xff0c;会触发hashchange事件&#xff0c;且history栈中会增加一条记录&#xff0c;但页面不会重新加载——实现HashRouter的关键history.pushState(state, , URL)执行后&#xf…...

生物信息学中的可重复性研究

科学就其本质而言&#xff0c;是累积渐进的。无论你是使用基于网络的还是基于命令行的工具&#xff0c;在进行研究时都应保证该研究可被其他研究人员重复。这有利于你的工作的累积与进展。在生物信息学领域&#xff0c;这意味着如下内容。 工作流应该有据可查。这可能包括在电脑…...

css-img图像同比缩小

1. HTML 中使图像按比例缩小 CSS 来控制图像的大小&#xff0c;并保持其宽高比 <!DOCTYPE html> <html> <head><style>.image-container {width: 300px; /* 设置容器宽度 */height: auto; /* 让高度自适应 */}.image-container img {width: 100%; /* …...

SpringBoot+Prometheus+Grafana搭建应用监控系统

1.应用监控系统介绍 SpringBoot的应用监控方案比较多&#xff0c;SpringBootPrometheusGrafana是比较常用的一种解决方案&#xff0c;主要的监控数据的处理逻辑如下&#xff1a; SpringBoot 的 actuator 提供了应用监控端点&#xff0c;可以对外暴露监控数据信息。Prometheu…...

QT c++和qml交互实例

文章目录 一、demo效果图二、c和qml交互的基本方式1、qml 调用 C 类对象2、C 类对象调用 qml3、qml 给 C 发送信号4、C 给 qml 发送信号 三、关键代码1、工程结构图2、c代码MainWindow.cppMainQuickView.cppStudentInfoView.cppStudentInfoModel.cpp 3、qml代码main.qmlMainQui…...

mysql基础-数据操作之增删改

目录 1.新增数据 1.1单条数据新增 1.2多条数据新增 1.3查询数据新增 2.更新 2.1单值更新 2.2多值更新 2.3批量更新 2.3.1 批量-单条件更新 2.3.2批量-多条件更新 2.4 插入或更新 2.5 联表更新 3.删除 本次分享一下数据库的DML操作语言。 操作表的数据结构&#xf…...

写字母(文件)

请编写函数&#xff0c;将大写字母写入文件中。 函数原型 void WriteLetter(FILE *f, int n);说明&#xff1a;参数 f 为文件指针&#xff0c;n 为字母数目(1 ≤ n ≤ 26)。函数将前 n 个大写英文字母写入 f 所指示的文件中。 裁判程序 #include <stdio.h> #include &…...

基于Jackson自定义json数据的对象转换器

1、问题说明 后端数据表定义的id主键是Long类型&#xff0c;一共有20多位。 前端在接收到后端返回的json数据时&#xff0c;Long类型会默认当做数值类型进行处理。但前端处理20多位的数值会造成精度丢失&#xff0c;于是导致前端查询数据出现问题。 测试前端Long类型的代码 …...

【Java】缓存击穿解决方案

文章目录 什么是SingleFlight&#xff1f;优化缺点优化策略 什么是SingleFlight&#xff1f; SingleFlight是go语言中sync包中的一个东西。它用于确保在并发环境下某个操作&#xff08;例如&#xff0c;函数调用&#xff09;即使被多个goroutine同时请求&#xff0c;也只会被执…...

【HarmonyOS】掌握 Stage 模型的核心概念与应用

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…...

2024年甘肃省职业院校技能大赛 “信息安全管理与评估”赛项样题卷①

2024年甘肃省职业院校技能大赛 高职学生组电子与信息大类信息安全管理与评估赛项样题 第一阶段&#xff1a;第二阶段&#xff1a;模块二 网络安全事件响应、数字取证调查、应用程序安全第二阶段 网络安全事件响应第一部分 网络安全事件响应第二部分 数字取证调查第三部分 应用程…...

我的AI之旅开始了

知道重要&#xff0c;但是就是不动。 今天告诉自己&#xff0c;必须开始学习了。 用这篇博文作为1月份AI学习之旅的起跑点吧。 从此&#xff0c;无惧AI&#xff0c;无惧编程。 AI之路就在脚下。 AI&#xff0c;在我理解&#xff0c;就是让机器变得更加智能&#…...

Day25 235二叉搜索树的公共祖先 701二叉搜索树插入 450二叉搜索树删除

235 二叉搜索树的最近公共祖先 如果利用普通二叉树的方法&#xff0c;就是利用后序遍历回溯从低向上搜索&#xff0c;遇到左子树有p&#xff0c;右子树有q&#xff0c;那么当前结点就是最近公共祖先。本题是二叉搜索树&#xff0c;所以说是有序的&#xff0c;一定能够简化上面…...

android系列-init 挂载文件系统

1.init 挂载文件系统 //android10\system\core\init\main.cppint main(int argc, char** argv) {return FirstStageMain(argc, argv); } //android10\system\core\init\first_stage_init.cppint FirstStageMain(int argc, char** argv) {CHECKCALL(mount("tmpfs",…...

Spring 七种事务传播性介绍

作者&#xff1a;vivo 互联网服务器团队 - Zhou Shaobin 本文主要介绍了Spring事务传播性的相关知识。 Spring中定义了7种事务传播性&#xff1a; PROPAGATION_REQUIRED PROPAGATION_SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED…...

Count the Colors ZOJ - 1610

题目链接 题意&#xff1a; 给定n个区间[ l, r ]和颜色c, 每次给[l, r]涂上c这个颜色. 后面的涂色会覆盖之前的涂色. 最后要求输出区间[0, 8000]中每种颜色及其出现的次数, 如果该颜色没有出现过则不输出. 思路&#xff1a;典型的线段树区间染色问题&#xff0c;一般这种题…...

MATLAB点云处理总目录

一、点云滤波 原始点云包含过多噪点和冗余点&#xff0c;滤波和采样往往是点云预处理的必要步骤 1.滤波 重复点去除 NAN或INF无效点去除 自定义半径滤波 2.采样 基于空间格网的点云抽稀 随机下采样 均匀体素下采样 非均匀体素下采样 二、邻近搜索 如何组织点云快速获取当前…...

C语言逗号表达式如何计算

在 C 语言中&#xff0c;逗号表达式是一种特殊的表达式形式&#xff0c;它由逗号分隔的多个表达式组成。 逗号表达式的计算过程如下&#xff1a;1、从左到右依次计算每个表达式的值。2、最终返回的值是最右边表达式的值。3、逗号表达式的求值过程是顺序执行的&#xff0c;不会…...

Ubuntu 本地部署 ChatGPT-Next-Web

Ubuntu 本地部署 ChatGPT-Next-Web 文章目录 Ubuntu 本地部署 ChatGPT-Next-Web ChatGPT-Next-Web 项目地址&#xff1a;https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web 本文主要演示如何在 Ubuntu 本地&#xff08;默认是端口 3000&#xff09;部署 ChatGPT-Next-Web&am…...

小程序商城搭建:快速入门指南

随着移动互联网的普及&#xff0c;小程序商城逐渐成为了商家们进行线上销售的重要渠道。如果你也想搭建一个小程序商城&#xff0c;那么本文将为你介绍如何使用乔拓云这一第三方小程序搭建平台来轻松搭建自己的小程序商城。 一、选择合适的第三方小程序搭建平台 在选择第三方小…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...