浅谈前端路由原理hash和history

news/2024/4/27 19:49:26

1、认识前端路由

本质

前端路由的本质,是监听 url 地址或 hash 值的改变,来切换渲染对应的页面组件

前端路由分为两种模式
hash 模式
history 模式
两种模式的对比

image.png

2、hash 模式

(1)hash 定义

hash 模式是一种把前端路由的路径用 # 拼接在真实 url 后面的模式
在hash模式下,本质上是修改window.location.href实现的。
前端路由的改变依托于#锚点,而锚点后边的值我们可以通过修改window.location.hash的值来修改,每一次hash值的变化都会导致触发hashchange这个事件,hash模式就是通过 hashchange 事件来 监听 hash 值的改变从而渲染页面对应的组件。
在hash模式下修改页面不会刷新,因此hash模式不会向后端发送http请求,不会导致浏览器向后端发送请求。

(2)location

使用 location.hash 获取 hash 值
location 是 window.location 或者 document.location 的简写模式,window.location 对象包含了当前 URL 的信息,并提供了一系列属性来访问和操作 URL。

(3)location 的常用属性

href:获取或设置完整的 URL。
host:获取或设置主机名和端口号。
hostname:获取或设置主机名。
protocol:获取或设置协议部分(如 "http:" 或 "https:")。
pathname:获取或设置 URL 的路径部分。
search:获取或设置 URL 的查询部分(即问号后面的部分,包括问号)。
hash:获取或设置 URL 的片段标识部分(即井号后面的部分,包括井号)。
origin:获取只读属性,表示 URL 的源部分(协议+主机+端口)。
通过访问 window.location 对象的这些属性,可以方便地获取当前页面的 URL 信息,并且在需要时进行相应的修改。这些属性对于处理 URL 相关的逻辑非常有用。

(4)location 常用方法

作用: 实现对当前页面 URL 的重新加载、跳转等操作,方便地进行页面控制和导航

方法

  1. assign(url):加载(显示指定的 URL 的内容(加载新的文档并替换当前文档,类似于用户点击链接跳转页面。例如:window.location.assign('https://www.baidu.com'))
  2. replace(url):刷新当前页面(用新的文档替换当前文档,不会在历史记录中生成新的条目。例如:window.location.replace('https://www.baidu.com'))
  3. reload():替换当前的资源(重新加载当前文档。如果带有参数 forceReload 为 true,则会强制从服务器重新加载文档,而不使用缓存。例如:window.location.reload(true))。

(5)window.onhashchange 事件
当 URL 的片段标识符(hash 值)更改时,将触发 hashchange 事件 (跟在#符号后面的 URL 部分,包括#符号)。
可以使用 addEventListener 监听 hashchange 事件:

window.addEventListener('hashchange', function() {console.log('hash值被修改了');console.log('hashchage 事件被触发了');
}, false);

使用 onhashchange 事件处理程序

function locationHashChanged() {if (location.hash === '#/about') {console.log("欢迎进入about页面");}
}
window.onhashchange = locationHashChanged;
// hash值的改变也会触发 window.onpopstate事件,onpopstate事件在 history模式中再做介绍
window.addEventListener("popstate", () => {console.log("popstate 事件被触发了");
})

直接修改浏览器url地址,添加 hash 值 #/about。可以看出,修改 hash 值会优先触发 popstate 事件,然后再触发 hashchange 事件:

3、history 模式

(1)history 定义

history 是 HTML5 提供的新特性,允许开发者直接更改前端路由,也就是更改 url 地址而无需向后端发送 http 请求。
history 是 window.history 的简写模式,是 History 构造函数的实例化对象。
History 接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录。
也就是说 History 里面保存着当前标签页的所有浏览页面的访问记录。

(2)history API

实例化对象属性

length 会话历史记录中元素的数目,包括当前加载的页面
Integer(整型数值)
scrollRestoration 设置浏览器的默认滚动行为 auto(默认值,浏览器自动滚动) / manual(关闭浏览器自动滚动)
state 返回一个表示历史堆栈顶部的状态的任意值 
any(任意值)

实例化对象方法

back() 在会话历史记录中向后移动一页。如果没有上一页,则此方法调用不执行任何操作 window.history.back()
forward() 在会话历史中向前移动一页 window.history.forward();
go() go方法从会话历史记录中加载特定页面 window.history.go(-1); 负值表示向后移动back(),正值表示向前移动forward(); 值为0或不传时重新加载当前页面
pushState() 向当前浏览器历史中添加记录 history.pushState(state, title[, url])
replaceState() 修改当前历史记录实体,可以更新 state 对象以及 URL 地址。 history.replaceState(stateObj, title[, url]);

history.pushState()的使用
history.pushState() 方法接收三个参数:

state:一个对象,popState 事件触发时,state 对象会传入回调函数。如无需传参,则设置为 null 。
title:新页面的标题,但是所有浏览器目前都忽略这个值,因此可以设置为空字符串 "" 或者 null 。
url:新的网址地址,必须与当前页面处于同一个域下,浏览器的地址栏将显示这个网址。

接下来做一个测试,有一个 a.html 页面:
使用 pushState 方法添加一条记录到 History 会话历史中,并传参, pushState 方法只是更新了 url 地址,而页面未跳转。

history.replaceState()的使用
history.replaceState() 方法接收的参数与 history.pushState() 方法相同,唯一的不同是,使用 replaceState 会更新当前页面的记录,包括 state 对象和 URL 地址。
举个例子,使用 pushState 添加 a.html b.html c.html 三个记录,然后使用 replaceState 添加 d.html ,最后查看历史记录栈中收录了几条历史记录:
由上图可知,历史记录栈中只存有三条记录,即 ["a.html", "b.html", "d.html"]。原因就是 replaceState 将 c.html 替换为了 d.html。
所以使用 history.back() 会返回 b.html。
使用 history.forward() 也只会显示 d.html :

window.onpopstate 事件

window.onpopstate 事件是用来监听浏览历史记录变化的。
调用 history.pushState() 或者 history.replaceState() 不会触发 popstate 事件。popstate 事件只会在浏览器某些行为下触发,比如点击前进、后退按钮(或者在 JavaScript 中调用 history.back()、history.forward()、 history.go() 方法)。即,在同一文档的两个历史记录条目之间导航会触发该事件。
使用 addEventListener 监听 popstate 事件:

window.addEventListener('popstate', function(event) {console.log(event);
}, false);

使用 onpopstate 事件处理程序

function historyStateChanged(event) {console.log(event);
}
window.onpopstate= historyStateChanged;
// 测试,使用 popstate 监听记录栈的改变:
window.addEventListener("popstate", (event) => {console.log(event);
})

使用 pushState 以及 replaceState 并未触发 popstate 事件:

使用 history.back() ,触发了 popstate 事件并打印了参数 event
event事件对象中保存着 state 对象。

4、解决history模式下页面刷新404问题

在 history 下,你可以自由的修改 path,但刷新页面时,如果服务器中没有相应的响应或者资源,则会出现404页面,因为刷新页面会发送 http 请求。也就是说,使用 history 路由模式,需要通过服务端来允许地址可访问,后端也必须配置了当前资源路径地址才行。
如果后台部署使用了 nginx,可以对 nginx 进行如下配置来解决页面刷新问题(摘录):

server {listen 8080;server_name  localhost;location / {alias /Data/nginx/portal/;index  /index.html;try_files $uri $uri/ /index.html;}
}

技术前沿拓展

前端开发,你的认知不能仅局限于技术内,需要发散思维了解技术圈的前沿知识。细心的人会发现,开发内部工具的过程中,大量的页面、场景、组件等在不断重复,这种重复造轮子的工作,浪费工程师的大量时间。

介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,实现快速开发,提升工作效率;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3。如果你有闲暇时间,可以做个知识拓展。

看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/11054.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

C语言动态内存管理

CSDN成就一亿技术人 目录 一.为什么要存在动态内存分配 二.动态内存函数 1.malloc和free 2.calloc 3.realloc 三.常见的动态内存错误 1.对NULL指针的解引用操作 2.对动态开辟空间的越界访问 3.对非动态开辟内存使用free释放 4.使用free释放一块动态开辟内存的一…

Controller中接收数组参数

1、场景 需要根据用户id集合批量删除用户数据,前端使用post请求,controller中参数接收数组参数并根据用户id删除用户基本信息 2、分析处理: 2.1、前端请求类型contentType:application/json 请求体中为json字符串,后端新建一个U…

springboot网站开发如何配置log4j日志插件

springboot网站开发如何配置log4j日志插件!为了便于服务器等环境下的错误情况的排查根源,还是很有必要使用日志插件的,它可以记录下我们提前埋下的锚点信息。 在遇到故障,查看这些锚点记录的日志信息,可以快速高效的解…

基于单片机的实时水质监测系统设计

摘要:传统的水质监测存在人工成本高,取样时间长等诸多问题。为了解决这些问题,本文设计了一款基于单片机的实时水质监测系统,通过传感器采集到的数据,单片机通过zigbee 収送至云端,结合上位机软件可以实现实时的信息采集处理,实现了高敁、智能的水质监测工作。 兲键词:…

戳-考察C++基础的两道小题

昨天分享了一天本来是考察unique_ptr禁止拷贝行为的,但是粘贴的时候贴成正确代码了,于是,今天继续找两道小题来练练手。 今天这两道小题,你能回答上来不,题目1有至少6处错误,你能找到几个?题目2…

【ZooKeeper】1、基本介绍

本文基于 Apache ZooKeeper Release 3.7.0 版本书写 作于 2022年3月6日 14:22:11 转载请声明 1、Zookeeper是什么? 由ZooKeeper的官网介绍可知: ZooKeeper 是Apache原子基金会下一个开源的、用于提供可靠的分布式协同的服务器。 ZooKeeper 可以用来 配置…