浅谈前端路由原理hash和history

news2024/11/24 16:38:23

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.coloradmin.cn/o/1531624.html

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

相关文章

管理类联考–复试–英文面试–问题--规划介绍原因做法--纯英文版

借鉴 https://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.clickhttps://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.click https://ttsreader.com/zh/https://ttsreader.com/zh/ 规划 视频版…

MyBatis3源码深度解析(十七)MyBatis缓存(一)一级缓存和二级缓存的实现原理

文章目录 前言第六章 MyBatis缓存6.1 MyBatis缓存实现类6.2 MyBatis一级缓存实现原理6.2.1 一级缓存在查询时的使用6.2.2 一级缓存在更新时的清空 6.3 MyBatis二级缓存的实现原理6.3.1 实现的二级缓存的Executor类型6.3.2 二级缓存在查询时使用6.3.3 二级缓存在更新时清空 前言…

Java基础 学习笔记八

控制语句 分支语句 switch switch语句完整格式 expression 中执行完必须是个值并且必须是 int 或者 枚举 或者 字符串类型break语句只要执行,switch就要结束default语句不是必须的,但是建议写上,这样程序更加健壮 switch(expression){//exp…

浅谈 电脑和车的对比

https://www.zhihu.com/question/547115488 电脑CPU与汽车发动机有哪些相同点与不同点? - 知乎 就想机械硬盘一样 我们的技术可能达不到 但是我们可以弯道超车 比如长江存储的SSD可以取代 以前的机械硬盘

如何基于香橙派AIpro开发AI推理应用

简介 香橙派AIpro开发板采用昇腾AI技术路线,接口丰富且具有强大的可扩展性,提供8/20TOPS澎湃算力,可广泛使用于AI边缘计算、深度视觉学习及视频流AI分析、视频图像分析、自然语言处理等AI领域。通过昇腾CANN软件栈的AI编程接口,可…

深度学习pytorch——统计属性(持续更新)

矩阵范数 vs 向量范数 向量范数 1-范数:所有元素的绝对值之和。 2-范数:所有元素的平方之和,在开根号。 p-范数:所有元素的绝对值的p次方之和,再求其1/p次方。 例:向量X[2, 3, -5, -7] ,求向…

深入理解Linux内核页表映射分页机制原理

深入理解Linux内核页表映射分页机制原理 前言 操作系统用于处理内存访问异常的入口操作系统的核心任务是对系统资源的管理,而重中之重的是对CPU和内存的管理。 为了使进程摆脱系统内存的制约,用户进程运行在虚拟内存之上,每个用户进程都拥…

静态网络配置

一、查看网络命令 1.命令行查看网络配置 1、查看ip\硬件设备-网卡 ifconfig -a ifconfig ens160 网卡名称 ip addr show ip addr show ens160 nmcli device show ens160 nmcli con up ens160 2、主机名称 hostname hostname hfj.huaxia.com 3、查看路由和网关 rou…

(C++20) jthread中stop_token的基础使用

(C20) jthread中stop_token的基础使用 文章目录 (C20) jthread中stop_token的基础使用C20 jthread使用方式循环判断条件变量condition_variable_any stop回调 std::stop_callbackEND C20 jthread std::jthread - cppreference.com std::stop_token - cppreference.com std::sto…

springboot3以及上版本引入RocketMQTemplate显示could not be found.

1. 问题所在 springboot3以及上版本引入RocketMQTemplate显示could not be found? 在springboot3时,直接通过依赖来注入RocketMQTemplate会报错,会显示没有这个对象。 这是因为在Springboot3以前的版本,自动装配是通过读取所有jar…

Docker容器化技术(docker-compose安装部署案例)

docker-compose编排工具 安装docker-compose [rootservice ~]# systemctl stop firewalld [rootservice ~]# setenforce 0 [rootservice ~]# systemctl start docker[rootservice ~]# wget https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-…

xinput1_3.dll丢失如何修复,xinput1_3.dll的安装修复教程分享

在Windows操作系统环境下,我们经常会遇到一些错误提示,其中之一就是“找不到xinput13.dll”。由于xinput1_3.dll是微软DirectX SDK的一部分,主要用于支持游戏手柄和其他外部设备的输入功能,缺失这一动态链接库文件可能导致某些依赖…

高顿咨询如何用国产CRM实现经验决策到数据决策的跨越

编者按 近日,Salesforce 移动应用在中国大陆苹果应用商店的下架,预示着今年CRM国产化替代即将迎来高潮。CRM作为距离业务最近的软件,被公认为是企业数字化转型、高质量发展的核心系统之一。“企业如何选择一款真正满足自身业务需求的本土化C…

邮件客户端 Thunderbird 简单配置

1. 基本情况介绍 原来使用的邮箱客户端是 Office 365 自带的 Outlook 365切换原因:新装电脑,发现原 Outlook 中的账号信息无法迁移,需要耗费大量时间手动配置邮箱使用的邮箱:微软 O365 邮箱、qq 邮箱、163 邮箱、公司私有邮箱 …

stable diffusion webui ubuntu 安装

1.git clone 下来 GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UIStable Diffusion web UI. Contribute to AUTOMATIC1111/stable-diffusion-webui development by creating an account on GitHub.https://github.com/AUTOMATIC1111/stable-diffus…

阻止默认行为 e.preventDefault()搭配passive:false才有效

正确情况 如果想阻止默认行为,那么 e.preventDefault()搭配passive:false才是正解 document.addEventListener(touchmove,(e)>{ e.preventDefault() console.log(123,123);},{passive:false}) 如果搭配 passive:false,则会报警告 e.preventDefault()搭配passive:true会报…

FREERTOS软件定时器

FreeRTOS 也提供了定时器功能,不过是软件定时器,软件定时器的精度肯定没有硬件定时器那么高,但是对于普通的精度要求不高的周期性处理的任务来说够了。当MCU的硬件定时器不够的时候就可以考虑使用 FreeRTOS 的软件定时器。 软件定时器允许设置…

HCIP【静态路由综合实验练习】

目录 实验要求: 实验过程: 一:首先设计实验 二:IP地址的划分(基于192.168.1.0/24) 在ensp中对路由器的相关命令进行配置: 三:配IP地址 (1)首先给所有设…

conda创建环境网络报错解决办法

文章目录 一、报错示例&#xff1a;二、解决办法&#xff1a;2.1 查看配置 conda config --show-sources2.2 修改文件 /home/XXXX/.condarc 一、报错示例&#xff1a; UnavailableInvalidChannel: HTTP 404 NOT FOUND for channel nvidia <http://mirrors.tuna.tsinghua.ed…

uniapp 开发微信小程序 出现启用组件按需注入问题如何解决

问题描述 在使用uniapp 开发微信小程序&#xff0c;进行上架发布时 代码质量栏 出现启用组件按需注入问题。 虽然现实代码上传成功&#xff0c;但是作为一个吹毛求疵的老猿人&#xff0c;肯定是无法容忍的。那么如何解决呢&#xff1f; 问题解决方案 在uniapp端&#xff0c…