Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
文章目录
- 一、前言
- 二、hash模式
- hashchange 事件:
- 三、history模式
- 方法:
- 1、history.go():
- 2、history.back():
- 3、history.forward():
- 4、History.replaceState()
- 5、History.pushState()
- popState 事件
- 四、nginx配置
- 五、原生 Node.js配置
- 六、注意
- 七、如何选择合适的路由模式
一、前言
单页面应用(SPA)的核心思想之一,就是更新视图而不重新请求页面,简单来说,它在加载页面时,不会加载整个页面,只会更新某个指定的容器中的内容。对于大多数单页面应用,都推荐使用官方支持的vue-router。
在实现单页面前端路由时,提供了两种方式,分别是hash模式和history模式,根据mode参数来决定采用哪一种方式。
const router = new VueRouter({routes,mode: "history" // 或者 "hash"
})
二、hash模式
http://example.com/#/home
Hash模式是Vue.js中默认的URL管理模式。在Hash模式下,URL中的#符号用于标识页面状态的变化。当页面中的路由发生改变时,Vue.js会使用Hash模式来更新URL,并在页面中渲染相应的组件。
- Hash模式是通过监听hashChange事件来实现的,前端js把当前hash地址对应的组件渲染到浏览器中。
- 在地址栏URL上有#号。
- 通常用于单页面应用(SPA),支持页面内的导航,不会刷新页面,也不会影响服务器。
- Hash出现在URL中,但不包括在http请求中,对后端没有影响。
- 在进行URL跳转时,如果只改变hash,不会重新加载页面。
hashchange 事件:
当hash值改变时会触发这个事件,通过 location.hash 获取到最新的 hash 值
注意:
- hash 值的变化不会导致浏览器像服务器发送请求
- location.hash可以获取hash值
- hashchange是hash值发生改变的调用的函数
语法:
window.onhashchange = function () {console.log(location.hash);
};// 或window.addEventListener('hashchange', ()=>{console.log(location.hash);
});
三、history模式
http://example.com/home
History模式是另一种URL管理模式,它使用HTML5的History API来实现URL的变化和页面的刷新。在History模式下,URL中的#符号被移除,取而代之的是通过History API来管理页面的状态。
History模式的优点在于它能够实现平滑的页面过渡,提高用户体验。同时,由于URL中不包含#符号,因此也适用于搜索引擎优化。然而,History模式需要在服务器端进行额外的配置,以确保能够正确地处理不同的URL路径请求。
- History模式是通过调用history.pushState方法(或者replaceState)并且监听popstate事件来实现的。history.pushState会追加历史记录,并更换地址栏地址信息,但是页面不会刷新。
- 需要服务器端做额外的配置,否则可能会出现刷新页面时的404错误。
- 在进行URL跳转时,即使只改变hash,也需要重新加载页面(如果当前页面不是SPA)。
- 支持浏览器的前进、后退功能。
方法:
1、history.go():
通过当前页面的相对位置从浏览器历史记录(会话记录)异步加载页面。
参数:
- 参数为 -1 的时候为上一页,
- 参数为 1 的时候为下一页。
- 当你指定了一个越界值,例如:当会话历史记录中没有之前访问的页面时,则传参的值为 -1,那么这个方法没有任何效果也不会报错。
- 调用没有参数的 go() 方法或者参数值为 0 时,重新载入当前页面。
- Internet Explorer 允许你指定一个字符串,而不是整数,以转到历史记录列表中的特定 URL。
2、history.back():
此异步方法转到浏览器会话历史的上一页,与用户单击浏览器的 Back 按钮的行为相同。等价于 history.go(-1)。
调用此方法回到会话历史的第一页之前没有效果并且不会引发异常。
3、history.forward():
此异步方法转到浏览器会话历史的下一页,与用户单击浏览器的 Forward 按钮的行为相同。等价于 history.go(1)。
调用此方法超越浏览器历史记录中最新的页面没有效果并且不会引发异常。
4、History.replaceState()
替换当前页在历史记录中的信息
语法:
history.replaceState(stateObj, title[, url])
参数:
-
stateObj:状态对象是一个 JavaScript 对象,它与传递给 replaceState 方法的历史记录实体相关联。
-
title:大部分浏览器忽略这个参数, 将来可能有用。在此处传递空字符串应该可以防止将来对方法的更改。或者,你可以为该状态传递简短标题。
-
url:可选,历史记录实体的 URL. 新的 URL 跟当前的 URL 必须是同源; 否则 replaceState 抛出一个异常。
5、History.pushState()
向历史记录中追加一条记录
语法:
pushState(stateObj, title, url)
参数:
- stateObj:一个用于表示历史记录状态的JavaScript对象。这个对象的内容会被添加到浏览器的历史堆栈中。这个参数是可选的。
- title:为新的历史记录条目提供标题。这个参数通常可以设置为null,因为大多数浏览器在显示历史记录列表时并不使用这个标题。
- url:可选,要添加到历史记录中的新URL。这个 URL 必须与当前页面处于同一个域中,否则浏览器可能会阻止这个操作。
优势:
-
pushState()设置的新的url可以是于当前url同源的任意url,而hash只可修改#后面的部分,因此只能设置与当亲url同文档的url。
-
pushState()设置的新的url可以与当前url一摸一样,这样也会把记录添加到栈中;而hash设置的新值必须与原来的不一样才会触发动作将记录添加到栈中。
-
pushState()通过stateObject参数可以添加任意类型的数据到记录中;而hash只可添加短字符串。
当你在SPA中使用history.pushState()或者history.replaceState()时,你可能会希望更改浏览器的URL,但是不刷新页面。这可以让你的SPA具有更好的用户体验,因为用户可以点击浏览器的后退和前进按钮来导航,而不需要在你的应用中进行额外的点击。
popState 事件
每当同一个文档的浏览历史(即history)出现变化时,就会触发popState事件。
注意:
-
仅仅调用pushState方法或replaceState方法,并不会触发该事件,只有用户点击浏览器后退和前进按钮时,或者使用js调用back、forward、go方法时才会触发。
-
该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件不会被触发。
-
页面第一次加载的时候,浏览器不会触发popState事件。
语法:
window.onpopstate = function (event) {console.log('location: ' + document.location);console.log('state: ' +JSON.stringify(event.state));
};// 或window.addEventListener('popstate', function(event) {console.log('location: ' + document.location);console.log('state: ' + JSON.stringify(event.state));
});
四、nginx配置
hash模式下,仅hash符号#之前的内容会被包含在请求中,比如http://www.example.com/home 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
history模式下,前端的url必须和实际后端发起请求的url一致,如http://example.com/about/id 。如果后端缺少对/about/id 的路由处理,将返回404错误。
在Vue.js中,可以使用vue-router库来实现Hash模式和History模式。通过配置vue-router的mode属性,可以选择使用Hash模式或History模式。需要注意的是,项目部署生产后,hash 模式能够正常使用,而 history 模式访问不到资源。hash 的改变不会发生请求,因此不影响服务器端,所以 nginx 不会拦截,而 history 模式则需要设置可访问的配置。
比如http://www.example.com/home 如果不进行配置,那么 nginx 默认会去找服务器目录下的 home 文件,而我们想要的效果则是依旧寻找 index 文件,home 则交给前端去处理,nginx 使用 try_files 配置即可实现该效果。
location / { root /www/wwwroot; index index.html; try_files $uri $uri/ /index.html;
}
五、原生 Node.js配置
const http = require('http')
const fs = require('fs')
const httpPort = 80http.createServer((req, res) => {fs.readFile('index.html', 'utf-8', (err, content) => {if (err) {console.log('We cannot open "index.html" file.')}res.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'})res.end(content)})
}).listen(httpPort, () => {console.log('Server listening on: http://localhost:%s', httpPort)
})
六、注意
给个警告,因为这么做以后,你的服务器就不再返回 404 错误页面,因为对于所有路径都会返回 index.html 文件。为了避免这种情况,你应该在 Vue 应用里面覆盖所有的路由情况,然后再给出一个 404 页面。
const router = new VueRouter({mode: 'history',routes: [{ path: '*', component: NotFoundComponent }]
})
或者,如果你使用 Node.js 服务器,你可以用服务端路由匹配到来的 URL,并在没有匹配到路由的时候返回 404,以实现回退。
更多详情请查阅 Vue 服务端渲染文档。
七、如何选择合适的路由模式
使用 Hash 模式:
- 如果你的项目不需要考虑兼容性问题,或者需要在旧版浏览器中支持路由功能。
- 如果你希望简化部署过程,只需将静态文件部署到服务器即可。
使用 History 模式:
- 如果你希望 URL 更加美观、简洁,不希望在 URL 中出现 # 符号。
- 如果你可以进行服务器配置,确保在直接访问 URL 时返回正确的页面。
- 如果你的项目不需要考虑旧版浏览器的兼容性问题。
相关文章:
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
文章目录 一、前言二、hash模式hashchange 事件: 三、history模式方法:1、history.go():2、history.back():3、history.forward():4、History.replaceState()5、History.pushState()popState 事件 四、nginx配置五、原…...

功能强大的免费SSL证书
一、数据加密的重要性 免费SSL证书的核心作用在于对网站的数据传输进行加密处理。当一个网站部署了SSL证书后,它能够将HTTP协议升级至HTTPS,这意味着所有在客户端(如浏览器)与服务器之间传输的信息都将被高强度的加密算法所保护。…...
在Vue中使用Web Worker详细教程
1.什么是Web Worker? Web Worker 是2008年h5提供的新功能,每一个新功能都是为了解决原有技术的的痛点,那么这个痛点是什么呢? 1.1 JavaScript的单线程 JavaScript 为什么要设计成单线程? 这与js的工作内容有关:js只…...
四、C#高级特性(动态类型与Expando类)
在C#中,动态类型和ExpandoObject类是两个与运行时类型系统相关的特性,它们提供了更灵活的数据处理能力。 动态类型 动态类型是一种特殊的类型,允许你在运行时解析和操作对象的成员,而不需要在编译时知道这些成员的细节。使用动态…...
贪心算法的“左最优“与“右最优“及其对应的堆处理和预处理方法
1 答疑 1.1 什么是贪心算法的"左最优"与"右最优" "左最优"和"右最优"是贪心算法中的两种策略: 左最优 (Leftmost Greedy): 在每一步选择中,总是选择最左边(最早出现的)可行的选项。 右…...

【Docker】容器的相关命令
上一篇:创建,查看,进入容器 https://blog.csdn.net/m0_67930426/article/details/135430093?spm1001.2014.3001.5502 目录 1. 关闭容器 2.启动容器 3.删除容器 4.查看容器的信息 查看容器 1. 关闭容器 从图上来看,容器 aa…...

Android BUG 之 Error: Activity class {} does not exist
项目场景: 更换包名,运行报错 问题描述 原因分析: 在替换包名的时候要确认,配置文件跟build中的保持一致,在更换后还要将旧包的缓存数据清理掉 解决方案: 1 替换后删除 app 下的build 文件夹 2 Rebuild Pr…...

听劝,年度规划有它真的很必要!
2024年的时间进度条已走过一周,完成全年的1/52。 新年的flag悄然立下:愿逆风如解意,税后八个亿。 在不确定的世界中,发财暴富终归是确定的目标。 相比2023年的卷,年底的即兴生活正在悄悄上演,上一秒还在…...
leetcode滑动窗口问题总结 Python
目录 一、理论 二、例题 1. 最长无重复字符串 2. 长度最小的子数组 3. 字符串的排列 4. 最小覆盖子串 5. 滑动窗口最大值 一、理论 滑动窗口是一类比较重要的解题思路,一般来说我们面对的都是非定长窗口,所以一般需要定义两个指针 left 和 right&…...

秒变办公达人,只因用了这5款在线协同文档app!
在日常工作中,我们不可避免地需要处理各种文档,有时你可能会为如何高效地管理这些文档而感到烦恼,或是不知道如何挑选合适的在线文档工具? 不用担心!在这篇文章中,我们将介绍5个好用的在线文档工具App&…...
镜头选型和计算
3.5 补充知识 一、单像元分辨率(单像素精度) 单像素精度是表示视觉系统综合精度的指标,表示一个像元对应检测目标的实际物理尺寸,是客户重点关注的 视觉系统参数; 计算公式1:单像素精度视野范围FOV/相机分辨…...

2024--Django平台开发-Django知识点(四)
1.知识回顾 创建项目:新项目、别人项目、新版版、老版本 项目目录(v1.0版本) 路由系统 常见路由编写加粗样式 /index/ 函数 /index/<str:v1> 函数 re_path(ryy/(\d{4})-(\d{2})-(\d{2})/, views.yy), re_path(ryy/(?…...

可狱可囚的爬虫系列课程 09:通过 API 接口抓取数据
前面已经讲解过 Requests 结合 BeautifulSoup4 库抓取数据,这种方式在抓取数据时还是比较方便快捷的,但是这并不意味着所有的网站都适合这种方式,并且这也不是抓取数据的最快方式,今天我们来讲一种更快速的获取数据的方式…...
2. Spring Boot 自动配置 Mybatis 流程
1. Spring Boot 自动配置 Mybatis 自动配置过程中做了3个主要bean的创建及很重要的一些事情。 sqlSessionFactory、sqlSessionTemplate、MapperScannerConfigurer 等配置bean的创建。sqlSessionFactory:解析 xml配置文件,并将MappedStatement放入到Has…...

Nginx配置反向代理实例一
Mac 安装Nginx教程 提醒一下:下面实例讲解是在Mac系统演示的; 反向代理实例一实现的效果 在浏览器地址栏输入www.testproxy.com, 跳转到系统Tomcat主页面。 第一步:在系统的 hosts 文件进行ip和域名对应关系的配置。 Mac 系统修改Hosts文…...

训练自己的GPT2
训练自己的GPT2 1.预训练与微调2.准备工作2.在自己的数据上进行微调 1.预训练与微调 所谓的预训练,就是在海量的通用数据上训练大模型。比如,我把全世界所有的网页上的文本内容都整理出来,把全人类所有的书籍、论文都整理出来,然…...

etcd储存安装
目录 etcd介绍: etcd工作原理 选举 复制日志 安全性 etcd工作场景 服务发现 etcd基本术语 etcd安装(centos) 设置:etcd后台运行 etcd 是云原生架构中重要的基础组件,由 CNCF 孵化托管。etcd 在微服务和 Kubernates 集群中不仅可以作为服务注册…...
如何彻底卸载Microsoft Edge浏览器
一、引语 随着微软推出全新的Edge浏览器,许多用户可能想要尝试或完全切换到其他浏览器。在这篇文章中,我们将向您介绍如何彻底卸载Microsoft Edge浏览器,以确保您的系统干净整洁。 二、通过系统设置卸载 1、首先,右键单击桌面上…...

Transformers 2023年度回顾 :从BERT到GPT4
人工智能已成为近年来最受关注的话题之一,由于神经网络的发展,曾经被认为纯粹是科幻小说中的服务现在正在成为现实。从对话代理到媒体内容生成,人工智能正在改变我们与技术互动的方式。特别是机器学习 (ML) 模型在自然语言处理 (NLP) 领域取得…...
判断两个对象某些字段的值是否相同
1、借助mybatis plus的方法 import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import lombok.SneakyThrows; import o…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

Python训练营-Day26-函数专题1:函数定义与参数
题目1:计算圆的面积 任务: 编写一个名为 calculate_circle_area 的函数,该函数接收圆的半径 radius 作为参数,并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求:函数接收一个位置参数 radi…...