SPA白屏卡顿痛点|1套手写Hash路由|彻底掌握前端路由底层原理
写单页应用总遇到这些糟心事传统多页面跳转整页刷新、白屏、加载慢移动端体验极差只会用Vue/React Router库底层原理一问三不知出bug无从排查分不清锚点#和前端Hash路由区别不知道hashchange事件怎么用读完本文你能收获搞懂MPA多页应用与SPA单页应用核心差异吃透Hash路由底层运行机制、浏览器URL规则两段完整可直接运行的实战代码锚点demo手写路由类开发踩坑避坑清单、Hash路由优缺点与适用场景从零手写简易路由库不用框架也能实现页面无刷新切换全文短句分段手机阅读无压力所有代码复制打开浏览器就能跑。一、先搞懂传统多页面MPA为什么又慢又卡1. 传统页面跳转流程以首页index.html跳转到about.html为例点击a标签链接浏览器读取完整URL向服务端发起全新HTTP请求服务器返回对应html静态文件浏览器清空当前页面完整重新渲染DOM、样式、脚本浏览器历史记录新增一条2. 致命缺点网速一般时跳转必白屏交互割裂页面公共头部、底部重复加载资源浪费无法局部刷新所有内容全部重绘移动端流量消耗更高流畅度差配套演示代码多页跳转demoindex.html!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0titleMPA多页首页/title/headbodyheadernavulliahrefindex.html首页/a/liliahrefabout.html关于我们/a/li/ul/nav/headermainh1首页内容/h1/mainfooter/footer/body/htmlabout.html!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0title关于我们/title/headbodyheadernavulliahrefindex.html首页/a/liliahrefabout.html关于我们/a/li/ul/nav/headermainh1我们/h1/main/body/html测试现象两个文件放在同一文件夹点击导航切换页面会完全刷新滚动条重置页面闪烁白屏。二、SPA单页应用解决方案Hash路由核心原理1. URL结构拆解完整URL示例http://www.baidu.com/u/123?a1b2#/page1protocolhttp/https 传输协议host域名/IP地址path/u/123资源路径queryString?a1b2查询参数hash#/page1哈希片段#开头2. Hash独一无二的特性修改hash部分浏览器不会向服务器发送任何请求hash变更会自动新增浏览器历史记录前进后退按钮可用触发原生hashchange事件JS可监听URL变化hash仅作用于浏览器本地服务端接收请求时会自动忽略#及后面内容3. 原生锚点# 和 前端Hash路由的区别基础锚点demo仅页面滚动无法切换页面内容!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0title锚点基础Demo/title/headbody!-- 页面锚点 --anametop/aahref#bottom去到底部/adivstyleheight:200vh;background-color:yellow/divahref#top回到顶部/adivstyleheight:300vh;background-color:red/divanamebottom/ascriptwindow.addEventListener(hashchange,function(e){console.log(hash变了);console.log(新地址,e.newURL);console.log(旧地址,e.oldURL);})/script/body/html原生锚点仅控制页面滚动定位不能切换页面内容SPA Hash路由约定#/xxx格式监听hash变化动态替换容器DOM实现多页面切换4. Hash路由完整运行流程导航a标签href写#/page1点击后URL更新页面不刷新浏览器触发hashchange事件JS捕获当前hash值切割#获取路由标识匹配提前注册好的路由回调函数替换#container容器内HTML实现局部渲染前进/后退浏览器自动修改hash重复执行渲染逻辑三、实战手写完整可运行Hash路由类无任何框架完整源码直接复制保存html打开即可运行!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8metanameviewportcontentwidthdevice-width, initial-scale1.0title手写HashRouter SPA/titlestylenav ul{display:flex;gap:20px;list-style:none;padding:0;}#container{margin-top:30px;font-size:20px;}/style/headbodyheadernavulliahref#/page1页面一/a/liliahref#/page2页面二/a/liliahref#/page3页面三/a/li/ul/nav/header!-- 路由内容挂载容器 --dividcontainer/divscriptclassHashRouter{constructor(){// 存储所有路由映射key路由路径 value渲染回调this.routers{};// 监听hash变化bind修正this指向为路由实例window.addEventListener(hashchange,this.load.bind(this));// 页面首次加载时执行一次渲染刷新页面不空白window.addEventListener(DOMContentLoaded,this.load.bind(this));}// 注册路由传入hash路径 页面渲染回调register(hashPath,callback){this.routers[hashPath]callback;}// 根据当前hash匹配并渲染页面load(){// location.hash格式 #/page1slice(1)切掉#得到 /page1constcurrentHashlocation.hash.slice(1);// 获取对应渲染函数constrenderFnthis.routers[currentHash];// 存在路由则执行渲染无匹配显示404if(renderFn){renderFn.call(this);}else{document.getElementById(container).innerHTMLh2404 页面不存在/h2;}}}// 初始化路由实例constrouternewHashRouter();constcontainerdocument.getElementById(container);// 注册三条路由规则router.register(/page1,()container.innerHTMLh2页面一内容/h2p这里是首页展示信息/p);router.register(/page2,()container.innerHTMLh2页面二内容/h2p关于我们介绍页面/p);router.register(/page3,()container.innerHTMLh2页面三内容/h2p联系我们表单页面/p);/script/body/html核心代码拆解constructor构造函数创建路由注册表this.routers存储路径与渲染函数绑定hashchange监听切换页面自动执行渲染增加DOMContentLoaded监听解决刷新页面空白问题register注册方法外部调用注册路由把路径和渲染回调存入对象解耦路由与页面逻辑load渲染核心方法location.hash.slice(1)去除#符号拿到纯净路由路径匹配注册表内函数无匹配返回404页面call(this)保证回调内this指向路由实例方便扩展四、Hash路由开发高频踩坑清单坑1页面刷新后内容空白原因仅监听hashchange页面首次加载不会触发事件解决构造函数增加DOMContentLoaded监听页面载入自动执行一次渲染坑2this指向丢失读取不到routers注册表原因hashchange事件回调默认this指向window解决使用.bind(this)绑定路由实例上下文坑3原生锚点和路由#冲突原因页面内存在#top、#bottom锚点会触发路由渲染逻辑解决统一路由前缀#/判断路径是否以/开头区分页面锚点与路由坑4空hash直接访问域名无默认首页优化扩展load方法增加兜底逻辑currentHash为空时默认渲染/page1首页load(){constcurrentHashlocation.hash.slice(1)||/page1;constrenderFnthis.routers[currentHash];// ...后续逻辑不变}坑5URL带查询参数解析异常场景#/page1?id100解决方案使用split(?)[0]截取纯路由路径constcurrentHashlocation.hash.slice(1).split(?)[0];五、Hash路由优缺点 适用场景✅ 优势零服务端配置静态服务器、GitHub Pages、本地打开html均可运行兼容性极强最低兼容IE8老项目、后台管理系统首选hash变更不会发送请求不会出现404刷新报错浏览器前进、后退、历史记录原生支持❌ 劣势URL带有#符号视觉上不够简洁美观不利于SEO优化搜索引擎抓取会忽略#后路径无法使用锚点定位页面需要自己做兼容处理适合使用Hash路由的场景内部后台管理系统、中台项目无SEO需求静态托管页面、线上预览Demo、本地离线项目老旧浏览器兼容、无权限修改后端服务配置不推荐场景C端官网、需要搜索引擎收录的页面优先History模式六、全文核心总结MPA多页应用每次跳转全页面刷新白屏卡顿SPA用前端路由解决该痛点Hash路由依靠URL#哈希片段 hashchange事件实现无刷新页面切换#后的内容不会传递给服务端无需后端配置部署成本极低手写路由核心三步监听hash变化、注册路由映射、动态替换容器DOM后台、静态Demo优先Hash面向公网、需SEO选择History路由

相关新闻

LLM文件编写:从Prompt工程到Agent工作流的实战指南

LLM文件编写:从Prompt工程到Agent工作流的实战指南

1. 项目概述:为什么“LLM文件编写”是当下最值得投入的技能? 如果你最近在关注AI应用开发,尤其是大语言模型(LLM)的落地,那么“LLM文件编写”这个词组一定高频出现在你的视野里。它听起来可能有点技术化&a…

2026/10/11 4:02:24 阅读更多 →
产品经理实战心法:从价值模型到决策机制,打造卓越产品

产品经理实战心法:从价值模型到决策机制,打造卓越产品

1. 从“用户价值”到“产品定义”:李想的产品实战心法最近几年,产品经理这个岗位的热度似乎有所回落,但“产品思维”却越来越成为各行各业从业者的底层能力。无论是做技术、做运营、做市场,甚至自己做点小生意,如何定义…

2026/10/11 4:02:24 阅读更多 →
PADS四层板HDMI高速PCB设计实战:从叠层规划到信号完整性优化

PADS四层板HDMI高速PCB设计实战:从叠层规划到信号完整性优化

1. 项目概述:为什么四层板是HDMI高速设计的“甜点”?刚接到一个带HDMI接口的项目,主控是RK3588这类高性能处理器,信号速率直奔几个Gbps去了。客户要求控制成本,板层不能太多。这时候,四层板就成了一个非常经…

2026/10/5 22:40:53 阅读更多 →

最新新闻

光储直柔:从刚性消费到柔性电网节点的建筑配电革命

光储直柔:从刚性消费到柔性电网节点的建筑配电革命

从“抽水马桶”变成“蓄水池”,这句话是我这两年和建筑业主聊配电改造时,最常用的一句类比。过去建筑用电是典型的刚性消费:光伏发多少、电网供多少,楼里就用多少,用不完的就浪费,不够了就向电网要&#xf…

2026/10/11 4:01:56 阅读更多 →
SAP MDG 功能范围说明(基于S/4HANA 2025)

SAP MDG 功能范围说明(基于S/4HANA 2025)

文章目录业务背景Master Data Governance (MDG)MDG, Central GovernanceMDG, ConsolidationMDG, Mass ProcessingMDG, Data quality managementMDG, Federated master data governanceMDG, Process analytics for master data主要功能业务背景 Master Data Governance (MDG) …

2026/10/11 4:01:55 阅读更多 →
Playwright自动化测试实战:从定位器到工程化落地

Playwright自动化测试实战:从定位器到工程化落地

1. 项目概述与整体设计思路1.1 为什么自动化测试在这个阶段值得重新选型我真正开始大规模把 Playwright 自动化测试用到业务项目里,差不多是在两年前。之前团队做 Web 端回归,用的还是老一套的 Selenium 体系,脚本写起来倒不难,真…

2026/10/11 4:01:55 阅读更多 →
Mac brew安装软件

Mac brew安装软件

安装brew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"brew 基本命令 1.Homebrew常用命令bre…

2026/10/11 4:01:55 阅读更多 →
鸿蒙化适配yaml_modify:YAML定点修改与配置治理实践

鸿蒙化适配yaml_modify:YAML定点修改与配置治理实践

改 YAML 这件事,做过配置文件自动化的人应该都有体会:读起来容易,改起来全是坑。尤其当文件里有注释、有嵌套结构、有历史遗留的乱序 key 时,常规做法——用解析库读进来、改掉、再序列化写出去——往往会把整个文件重排一遍&…

2026/10/11 4:01:55 阅读更多 →
安装谷歌浏览器

安装谷歌浏览器

安装谷歌浏览器 在众多电脑软件中浏览器应该是每台电脑的必备软件,如何选择浏览器,选择哪一款浏览器对于好多电脑小白来说可能不是那么在意,但事实上有一款合适的浏览器是相当重要的。 曾经我看过一个人的电脑,着实让我有些发疯&a…

2026/10/11 4:00:55 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →