【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的五个对象时,提到: location.hash发生改变后,会触发hashchange事件,且history栈中会增加一条记录,但页面不会重新加载——实现HashRouter的关键history.pushState(state, , URL)执行后…...
生物信息学中的可重复性研究
科学就其本质而言,是累积渐进的。无论你是使用基于网络的还是基于命令行的工具,在进行研究时都应保证该研究可被其他研究人员重复。这有利于你的工作的累积与进展。在生物信息学领域,这意味着如下内容。 工作流应该有据可查。这可能包括在电脑…...
css-img图像同比缩小
1. HTML 中使图像按比例缩小 CSS 来控制图像的大小,并保持其宽高比 <!DOCTYPE html> <html> <head><style>.image-container {width: 300px; /* 设置容器宽度 */height: auto; /* 让高度自适应 */}.image-container img {width: 100%; /* …...
SpringBoot+Prometheus+Grafana搭建应用监控系统
1.应用监控系统介绍 SpringBoot的应用监控方案比较多,SpringBootPrometheusGrafana是比较常用的一种解决方案,主要的监控数据的处理逻辑如下: SpringBoot 的 actuator 提供了应用监控端点,可以对外暴露监控数据信息。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操作语言。 操作表的数据结构…...
写字母(文件)
请编写函数,将大写字母写入文件中。 函数原型 void WriteLetter(FILE *f, int n);说明:参数 f 为文件指针,n 为字母数目(1 ≤ n ≤ 26)。函数将前 n 个大写英文字母写入 f 所指示的文件中。 裁判程序 #include <stdio.h> #include &…...
基于Jackson自定义json数据的对象转换器
1、问题说明 后端数据表定义的id主键是Long类型,一共有20多位。 前端在接收到后端返回的json数据时,Long类型会默认当做数值类型进行处理。但前端处理20多位的数值会造成精度丢失,于是导致前端查询数据出现问题。 测试前端Long类型的代码 …...
【Java】缓存击穿解决方案
文章目录 什么是SingleFlight?优化缺点优化策略 什么是SingleFlight? SingleFlight是go语言中sync包中的一个东西。它用于确保在并发环境下某个操作(例如,函数调用)即使被多个goroutine同时请求,也只会被执…...
【HarmonyOS】掌握 Stage 模型的核心概念与应用
从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是…...
2024年甘肃省职业院校技能大赛 “信息安全管理与评估”赛项样题卷①
2024年甘肃省职业院校技能大赛 高职学生组电子与信息大类信息安全管理与评估赛项样题 第一阶段:第二阶段:模块二 网络安全事件响应、数字取证调查、应用程序安全第二阶段 网络安全事件响应第一部分 网络安全事件响应第二部分 数字取证调查第三部分 应用程…...
我的AI之旅开始了
知道重要,但是就是不动。 今天告诉自己,必须开始学习了。 用这篇博文作为1月份AI学习之旅的起跑点吧。 从此,无惧AI,无惧编程。 AI之路就在脚下。 AI,在我理解,就是让机器变得更加智能&#…...
Day25 235二叉搜索树的公共祖先 701二叉搜索树插入 450二叉搜索树删除
235 二叉搜索树的最近公共祖先 如果利用普通二叉树的方法,就是利用后序遍历回溯从低向上搜索,遇到左子树有p,右子树有q,那么当前结点就是最近公共祖先。本题是二叉搜索树,所以说是有序的,一定能够简化上面…...
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 七种事务传播性介绍
作者:vivo 互联网服务器团队 - Zhou Shaobin 本文主要介绍了Spring事务传播性的相关知识。 Spring中定义了7种事务传播性: PROPAGATION_REQUIRED PROPAGATION_SUPPORTS PROPAGATION_MANDATORY PROPAGATION_REQUIRES_NEW PROPAGATION_NOT_SUPPORTED…...
Count the Colors ZOJ - 1610
题目链接 题意: 给定n个区间[ l, r ]和颜色c, 每次给[l, r]涂上c这个颜色. 后面的涂色会覆盖之前的涂色. 最后要求输出区间[0, 8000]中每种颜色及其出现的次数, 如果该颜色没有出现过则不输出. 思路:典型的线段树区间染色问题,一般这种题…...
MATLAB点云处理总目录
一、点云滤波 原始点云包含过多噪点和冗余点,滤波和采样往往是点云预处理的必要步骤 1.滤波 重复点去除 NAN或INF无效点去除 自定义半径滤波 2.采样 基于空间格网的点云抽稀 随机下采样 均匀体素下采样 非均匀体素下采样 二、邻近搜索 如何组织点云快速获取当前…...
C语言逗号表达式如何计算
在 C 语言中,逗号表达式是一种特殊的表达式形式,它由逗号分隔的多个表达式组成。 逗号表达式的计算过程如下:1、从左到右依次计算每个表达式的值。2、最终返回的值是最右边表达式的值。3、逗号表达式的求值过程是顺序执行的,不会…...
Ubuntu 本地部署 ChatGPT-Next-Web
Ubuntu 本地部署 ChatGPT-Next-Web 文章目录 Ubuntu 本地部署 ChatGPT-Next-Web ChatGPT-Next-Web 项目地址:https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web 本文主要演示如何在 Ubuntu 本地(默认是端口 3000)部署 ChatGPT-Next-Web&am…...
小程序商城搭建:快速入门指南
随着移动互联网的普及,小程序商城逐渐成为了商家们进行线上销售的重要渠道。如果你也想搭建一个小程序商城,那么本文将为你介绍如何使用乔拓云这一第三方小程序搭建平台来轻松搭建自己的小程序商城。 一、选择合适的第三方小程序搭建平台 在选择第三方小…...
Leptin30;YQQVLTSLPSQNVLQIANDLENLRDLLHLL (mouse)
一、基本信息名称: Leptin30(小鼠源瘦素功能片段肽)单字母序列: YQQVLTSLPSQNVLQIANDLENLRDLLHLL三字母序列: Tyr-Gln-Gln-Val-Leu-Thr-Ser-Leu-Pro-Ser-Gln-Asn-Val-Leu-Gln-Ile-Ala-Asn-Asp-Leu-Glu-Asn-Leu-Arg-Asp…...
矩阵按键的硬件设计与软件扫描实战
1. 矩阵按键的硬件设计要点 第一次接触矩阵按键时,我完全被它节省IO口的设计惊艳到了。想象一下,16个独立按键原本需要16个IO口,而4x4矩阵按键只需要8个IO口就能搞定。这种设计在资源受限的单片机项目中简直就是救命稻草。 硬件连接上有个容易…...
luci-app-unblockneteasemusic技术指南:解决网易云音乐播放限制问题
luci-app-unblockneteasemusic技术指南:解决网易云音乐播放限制问题 【免费下载链接】luci-app-unblockneteasemusic [OpenWrt] 解除网易云音乐播放限制 项目地址: https://gitcode.com/gh_mirrors/lu/luci-app-unblockneteasemusic 一、问题导向:…...
ICML 2026 开分!投稿群来了!还有IJCAI、CVPR 2026投稿群!
点击下方卡片,关注“CVer”公众号AI/CV重磅干货,第一时间送达点击进入—>【顶会/顶刊】投稿交流群添加微信:CVer2233,助手会拉你进群!扫描下方二维码,加入CVer学术星球!可获得最新顶会/顶刊上…...
swoole方案 WebSocket 下推消息优先级队列
WebSocket 推消息优先级队列 大白话先说清楚 普通弹幕: "哈哈哈哈哈" 优先级 1 (低) 礼物打赏: "送了火箭!" 优先级 2 (中) 系统广播: "服务器维护通知" 优先级 3 (高)队列里同…...
你有多难拒绝别人?免费个人边界感与拒绝能力测试,看清你的“不敢拒绝“根源
你有多难拒绝别人?免费个人边界感与拒绝能力测试,看清你的"不敢拒绝"根源 引言 你有没有过这样的时刻—— 朋友临时约你,你明明很累想休息,却还是答应了同事请你帮忙做不属于你的工作,你不好意思拒绝&…...
从零开始:用正则表达式处理日期时间格式的完整指南
从零开始:用正则表达式处理日期时间格式的完整指南 在数据处理和文本分析中,日期时间格式的校验一直是个高频需求。无论是表单验证、日志分析还是数据清洗,确保日期时间格式的正确性都至关重要。正则表达式作为文本处理的瑞士军刀,…...
Ubuntu16.04服务器上从零部署LaneNet车道线检测:Tusimple数据集处理全流程避坑指南
Ubuntu 16.04服务器部署LaneNet车道线检测全流程实战 在自动驾驶和智能交通系统中,车道线检测是一项基础而关键的技术。本文将详细介绍如何在Ubuntu 16.04服务器环境下,从零开始部署LaneNet车道线检测模型,并处理Tusimple数据集的全流程。不同…...
Vue项目中el-tabs标签栏的5个高级用法与避坑指南
Vue项目中el-tabs标签栏的5个高级用法与避坑指南 在Vue生态中,Element UI的el-tabs组件是构建标签式界面的首选方案。但很多开发者仅停留在基础使用层面,未能充分发挥其潜力。本文将揭示五个高阶技巧,助你打造更灵活、高效的标签系统。 1. 标…...
智慧医疗泡罩药板药片缺失缺陷检测数据集VOC+YOLO格式1300张3类别
注意数据集中图片大约500张是原图剩余为增强图片数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件)图片数量(jpg文件个数):1300标注数量(xml文件个数):1300…...
