当前位置: 首页 > 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;那么本文将为你介绍如何使用乔拓云这一第三方小程序搭建平台来轻松搭建自己的小程序商城。 一、选择合适的第三方小程序搭建平台 在选择第三方小…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...