浅谈前端路由原理hash和history

简介: 该文章详细解析了前端路由的两种模式——Hash模式与History模式的工作原理及其实现方式,并通过实例代码展示了如何在实际项目中运用这两种路由模式。

封面

🎹序言

众所周知, hashhistory 在前端面试中是很常考的一道题目。在学习本文内容之前,周一对 hashhistory 的认知可能就在 hashurl 里面多了个 # ,而 history 就不会。然后,我认知里还有一个是只有 history 才能做前后端分离,而 hash 跟前后端分离没有关系。然而,现实是……

吓到跌倒

对于前端路由来说, hashhistory 都可以用于前后端分离项目,且两者有各自的特点和各自的使用场景,在使用过程中主要要了解当前项目所处的场景,以便于更好地判断使用哪一种路由模式更佳。下面进入本文的讲解~😜

🎸一、前端路由原理

1、SPA

SPA,即单页面应用(Single Page Application)。所谓单页 Web 应用,就是只有一张 Web 页面的应用。单页应用程序 (SPA) 是加载单个 HTML 页面并在用户与应用程序交互时动态更新该页面的 Web 应用程序。浏览器一开始会加载必需的 HTMLCSSJavaScript ,所有的操作都在这张页面上完成,都由 JavaScript 来控制。

现如今,为了配合单页面 Web 应用快速发展的节奏,各类前端组件化技术栈层出不穷。近几年来,通过不断的版本迭代, vuereact 两大技术栈脱颖而出,成为当下最受欢迎的两大技术栈。

2、什么时候需要路由

对于现代开发的项目来说,稍微复杂一点的 SPA ,都需要用到路由。而 vue-router 正是 vue 的路由标配,且 vue-router两种模式hashhistory

下面就依据这两种模式来进行一一讲解。

🎷二、Hash模式

1、定义

hash 模式是一种把前端路由的路径用井号 # 拼接在真实 url 后面的模式。当井号 # 后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange 事件。

2、网页url组成部分

(1)了解几个url的属性

属性 含义
location.protocal 协议
location.hostname 主机名
location.host 主机
location.port 端口号
location.patchname 访问页面
location.search 搜索内容
location.hash 哈希值

(2)演示

下面用一个网址来演示以上属性:

//http://127.0.0.1:8001/01-hash.html?a=100&b=20#/aaa/bbb
location.protocal // 'http:'
localtion.hostname // '127.0.0.1'
location.host // '127.0.0.1:8001'
location.port //8001
location.pathname //'01-hash.html'
location.serach // '?a=100&b=20'
location.hash // '#/aaa/bbb'

3、hash的特点

  • hash变化会触发网页跳转,即浏览器的前进和后退。

  • hash 可以改变 url ,但是不会触发页面重新加载(hash的改变是记录在 window.history 中),即不会刷新页面。也就是说,所有页面的跳转都是在客户端进行操作。因此,这并不算是一次 http 请求,所以这种模式不利于 SEO 优化。hash 只能修改 # 后面的部分,所以只能跳转到与当前 url 同文档的 url

  • hash 通过 window.onhashchange 的方式,来监听 hash 的改变,借此实现无刷新跳转的功能。

  • hash 永远不会提交到 server 端(可以理解为只在前端自生自灭)。

🎺三、History模式

1、定义

history APIH5 提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL 地址而不重新发起请求

2、与hash的区别

我们用一个例子来演示, hashhistory 在浏览器下刷新时的区别。具体如下:

正常页面浏览

https://github.com/xxx 刷新页面

https://github.com/xxx/yyy 刷新页面

https://github.com/xxx/yyy/zzz 刷新页面

改造H5 history模式

https://github.com/xxx 刷新页面

https://github.com/xxx/yyy 前端跳转,不刷新页面

https://github.com/xxx/yyy/zzz 前端跳转,不刷新页面

3、history的API

下面阐述几种 HTML5 新增的 history API具体如下表:

API 定义
history.pushState(data, title [, url]) pushState主要用于往历史记录堆栈顶部添加一条记录。各参数解析如下:①data会在onpopstate事件触发时作为参数传递过去;②title为页面标题,当前所有浏览器都会忽略此参数;③url为页面地址,可选,缺少时表示为当前页地址
history.replaceState(data, title [, url]) 更改当前的历史记录,参数同上; 上面的pushState是添加,这个更改
history.state 用于存储以上方法的data数据,不同浏览器的读写权限不一样
window.onpopstate 响应pushState或者replaceState的调用

4、history的特点

对于 history 来说,主要有以下特点:

  • 新的 url 可以是与当前 url 同源的任意 url ,也可以是与当前 url 一样的地址,但是这样会导致的一个问题是,会把重复的这一次操作记录到栈当中。
  • 通过 history.state ,添加任意类型的数据到记录中。
  • 可以额外设置 title 属性,以便后续使用。
  • 通过 pushStatereplaceState 来实现无刷新跳转的功能。

5、存在问题

对于 history 来说,确实解决了不少 hash 存在的问题,但是也带来了新的问题。具体如下:

  • 使用 history 模式时,在对当前的页面进行刷新时,此时浏览器会重新发起请求。如果 nginx 没有匹配得到当前的 url ,就会出现 404 的页面。
  • 而对于 hash 模式来说, 它虽然看着是改变了 url ,但不会被包括在 http 请求中。所以,它算是被用来指导浏览器的动作,并不影响服务器端。因此,改变 hash 并没有真正地改变 url ,所以页面路径还是之前的路径, nginx 也就不会拦截。
  • 因此,在使用 history 模式时,需要通过服务端来允许地址可访问,如果没有设置,就很容易导致出现 404 的局面。

6、两者选择

下面我们再来介绍下在实际的项目中,如何对这两者进行选择。具体如下:

  • to B 的系统推荐用 hash ,相对简单且容易使用,且因为 hashurl 规范不敏感;
  • to C 的系统,可以考虑选择 H5 history ,但是需要服务端支持
  • 能先用简单的,就别用复杂的,要考虑成本和收益

🎻四、结束语

对于 hashhistory 来讲,要清楚两者的区别以及两者各自的使用场景,还有各自的使用特点和优缺点。以上文章只是对前端路由原理的浅谈,希望对大家有帮助~

另下方第三个彩蛋放了一篇关于实现 vue-router 的文章,学有余力的小伙伴有需要自取o!

🐣彩蛋 One More Thing

🏷️参考资料

jarvis👉在SPA项目的路由中,注意hash与history的区别

vue-router官方文档👉vue-router的两种模式

值得一看👉从使用到自己实现简单Vue Router看这个就行了

🏷️番外篇

  • 关注公众号星期一研究室,第一时间关注优质文章,更多精选专栏待你解锁~
  • 如果这篇文章对你有用,记得留个脚印jio再走哦~
  • 以上就是本文的全部内容!我们下期见!👋👋👋
相关文章
|
14天前
|
移动开发 缓存 前端开发
深入理解前端路由:原理、实现与应用
本书《深入理解前端路由:原理、实现与应用》全面解析了前端路由的核心概念、工作原理及其实现方法,结合实际案例探讨了其在现代Web应用中的广泛应用,适合前端开发者和相关技术人员阅读。
|
27天前
|
前端开发 开发者
本文将深入探讨 BEM 的概念、原理以及其在前端开发中的应用
BEM(Block-Element-Modifier)是一种前端开发中的命名规范和架构方法,旨在提高代码的可维护性和复用性。通过将界面拆分为独立的模块,BEM 提供了一套清晰的命名规则,增强了代码的结构化和模块化设计,促进了团队协作。本文深入探讨了 BEM 的概念、原理及其在前端开发中的应用,分析了其优势与局限性,为开发者提供了宝贵的参考。
44 8
|
22天前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
56 1
|
27天前
|
监控 前端开发 jenkins
Jenkins 在前端项目持续部署中的应用,包括其原理、流程以及具体的实现方法
本文深入探讨了Jenkins在前端项目持续部署中的应用,涵盖其基本原理、流程及具体实现方法。首先介绍了Jenkins的基本概念及其在自动化任务中的作用,随后详细解析了从前端代码提交到生产环境部署的全过程,包括构建、测试、部署等关键步骤。最后,强调了持续部署中的代码质量控制、环境一致性、监控预警及安全管理等注意事项,旨在帮助开发者高效、安全地实施持续部署。
53 5
|
2月前
|
缓存 JavaScript 前端开发
拿下奇怪的前端报错(三):npm install卡住了一个钟- 从原理搞定安装的全链路问题
本文详细分析了 `npm install` 过程中可能出现的卡顿问题及解决方法,包括网络问题、Node.js 版本不兼容、缓存问题、权限问题、包冲突、过时的 npm 版本、系统资源不足和脚本问题等,并提供了相应的解决策略。同时,还介绍了开启全部日志、使用替代工具和使用 Docker 提供 Node 环境等其他处理方法。
997 0
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
168 2
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
46 0
|
2月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
2月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
2月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
116 1