浅谈前端路由原理hash和history

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。如果你有闲暇时间,可以做个知识拓展。

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

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

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

相关文章

【运维笔记】VM 记录一次centos虚拟机和宿主机之间ping不通的问题

问题描述 环境:centos7,静态ipVM版本:VMware Workstation 16 pro,网络为nat映射模式问题: 一开始,虚拟机可以ping通宿主机,也可以ping通,也可以ping通外网(如 ping www.…

HarmonyOS(二十)——管理应用拥有的状态之LocalStorage(页面级UI状态存储)

LocalStorage是页面级的UI状态存储,通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内,在页面间共享状态。 本文仅介绍LocalStorage使用场景和相关的装饰器:LocalStorageProp和LocalS…

GaussDB(分布式)实例故障处理

一、说明 GaussDB Kernel实例出现故障时,可以按照本节的办法进行实例快速修复。 1、执行gs_om -t status --detail查看集群状态,cluster_state为Normal,balanced为No,请重置实例状态。 2、执行gs_om -t status --detail查看集群…

【开源】SpringBoot框架开发校园超市管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 供应商模块2.2 超市商品模块2.3 超市账单模块 三、系统设计3.1 前端架构设计3.2 后端架构设计 四、系统实现五、核心代码5.1 查询商品5.2 删除商品5.3 查询供应商5.4 查询账单5.5 新增账单 六、免责说明 一、摘要 1.1 …

「数据分析」之零基础入门数据挖掘

摘要:对于数据挖掘项目,本文将学习应该从哪些角度分析数据?如何对数据进行整体把握,如何处理异常值与缺失值,从哪些维度进行特征及预测值分析? 探索性数据分析(Exploratory Data Analysis&#…

测试平台——前端框架

一、创建vue项目 npm init vitelatest web_class wylWYLdeMacBook-Air testplatform % npm init vitelatest web_class ✔ Select a framework: › Vue ✔ Select a variant: › JavaScriptScaffolding project in /Users/wyl/workspace/testplatform/web_class...Done. Now…

构建一个前端智能停车可视化系统

引言 随着城市化进程的加速,停车难问题日益突出。智能停车可视化系统通过实时展示停车场的车位信息,帮助用户快速找到空闲车位,提高停车效率。 目录 引言 一、系统设计 二、代码实现 1. 环境准备 2. 安装依赖 3. 创建停车场组件 4. 集…

nodejs社区垃圾分类管理平台的设计与实现python-flask-django-php

近些年来,随着科技的飞速发展,互联网的普及逐渐延伸到各行各业中,给人们生活带来了十分的便利,社区垃圾分类管理平台利用计算机网络实现信息化管理,使整个社区垃圾分类管理的发展和服务水平有显著提升。 语言&#xf…

BRAS(宽带接入服务器)简介

文章目录 BRAS的主要功能IP地址分配功能AAA(认证、计费、授权) BRAS的工作流程vBRAS 宽带接入服务器(Broadband Remote Access Server,简称BRAS)是面向宽带网络应用的新型接入网关,它位于骨干网的边缘层,可…

阅读笔记(arXiv2022)Submodularity In Machine Learning and Artificial Intelligence

次模性在机器学习和人工智能中的应用 Bilmes, J. (2022). Submodularity in machine learning and artificial intelligence. arXiv preprint arXiv:2202.00132. 本文的核心内容概述: 1. **次模函数的基本概念**: - 次模函数是定义在有限集合上的集…

手机运营商二要素检测:重塑信任基石,筑牢信息安全屏障

随着移动互联网的普及和数字经济的快速发展,用户信息安全的重要性日益凸显。运营商二要素检测作为一种强大的安全验证机制,以其精准匹配与实时验证的特性,为各类应用场景提供了一种可靠的身份识别解决方案,正在成为众多企业和服务…

【Web应用技术基础】HTML(3)——表格

目录 题目1:原始表格 题目2:width、height 题目3: cellpadding 题目4:cellspacing、cellpadding 题目5:caption 题目6:rowspan 题目7:colspan 题目8:汇总题 题目1&#xff1…

Fetch、Axios 和 jQuery(Ajax) 三种常用的网络请求技术

Fetch、Axios 和 jQuery(Ajax) 是三种常用的网络请求技术,它们各自有着不同的特点和优势。本文将对这三种技术进行详细的介绍和比较,以帮助开发者更好地选择和使用合适的网络请求技术。 一、Fetch Fetch(浏览器自带) 是一种现代的网络请求 API&#xff…

Linux CentOS 7.6安装Redis 6.2.6 详细保姆级教程

1、安装依赖 //检查是否有依赖 gcc -v //没有则安装 yum install -y gcc2、下载redis安装包 //进入home目录 cd /home //通过wget下载redis安装包 wget https://download.redis.io/releases/redis-6.2.6.tar.gz //解压安装包 tar -zxvf redis-6.2.6.tar.gz3、编译 //进入解压…

CSS学习笔记:transform属性实现元素的位移、旋转、缩放

位移 实现居中的两种方法 绝对定位的盒子在父盒子中实现居中效果有两种方法 法一:margin 其中,left和top的值分别为子盒子自身宽高的一半 法二:translate 实现过渡效果 translate常常配合hover和transition使用,以实现鼠标悬停…

流畅的 Python 第二版(GPT 重译)(二)

第三章:字典和集合 Python 基本上是用大量语法糖包装的字典。 Lalo Martins,早期数字游牧民和 Pythonista 我们在所有的 Python 程序中都使用字典。即使不是直接在我们的代码中,也是间接的,因为dict类型是 Python 实现的基本部分。…

uniapp、vue2.6、H5,利用腾讯TRTC,快速跑通1v1视频功能

多人视频聊天室搭建,官网已有相关demo和案例,需要快速搭建多人聊天室直接进入以下网站: 实时音视频 Web & H5 (Vue2/Vue3)-视频通话(含 UI)-文档中心-腾讯云说明:https://cloud.tencent.com/document/…

Python 深度学习第二版(GPT 重译)(三)

七、使用 Keras:深入探讨 本章涵盖 使用 Sequential 类、功能 API 和模型子类创建 Keras 模型 使用内置的 Keras 训练和评估循环 使用 Keras 回调函数自定义训练 使用 TensorBoard 监控训练和评估指标 从头开始编写训练和评估循环 您现在对 Keras 有了一些经…

uni-app 中两个系统各自显示不同的tabBar

最近在一个uni-app项目中遇到一个需求,在登录页面成功登录以后需要判断身份,不同的身份的进入不同的tabBar页面,但是在uni-app项目中pages.json中的tabBar的list数组只有一个,且不能写成动态的,那如何实现这个需求呢?答案是需要我们自定义tabBar。 目录 1、我们确…

四、HarmonyOS应用开发-ArkTS开发语言介绍

目录 1、TypeScript快速入门 1.1、编程语言介绍 1.2、基础类型 1.3、条件语句 1.4、函数 1.5、类 1.6、模块 1.7、迭代器 2、ArkTs 基础(浅析ArkTS的起源和演进) 2.1、引言 2.2、JS 2.3、TS 2.4、ArkTS 2.5、下一步演进 3、ArkTs 开发实践…