前端路由hash模式以及history模式详解

news2024/10/5 18:29:05

在这里插入图片描述

文章目录

  • 前言
  • 一、hash 模式
    • 1、hash 定义
    • 2、location 对象
    • 3、window.onhashchange 事件
  • 二、history 模式
    • 1、history 定义
    • 2、history API
    • 3、window.onpopstate 事件
    • 4、解决history模式下页面刷新404问题

前言

在前后端分离的项目中,前端一般使用 SPA 单页面应用模式来开发项目。那么,什么是 SPA 呢?

单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。

我的理解:单页面应用就是改变页面的url地址,不会向后台发送请求,而是通过前端路由,动态渲染页面组件,url地址的改变与后台无关

而前端路由又分为两种模式:

  1. hash 模式
  2. history 模式

两种模式的对比:

对比hash 模式history 模式
url 显示url 中带"#"url 中不带"#"
回车刷新(浏览器刷新按钮)页面正常显示后端未配置则页面显示404
支持版本支持低版本浏览器和 IE 浏览器HTML5 新推出的 API

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

接下来让我们详细了解一下两种路由模式。

一、hash 模式

1、hash 定义

hash 模式是一种把前端路由的路径用 # 拼接在真实 url 后面的模式,通过 hashchange 事件监听 hash 值的改变来渲染页面对应的组件。hash 模式不会向后端发送 http 请求,所有的 hash 值操作都与后端无关。

使用 location.hash 获取 hash 值。

以 url 地址: http://localhost:8080/#/about 为例:

在这里插入图片描述

2、location 对象

location 是 window.location 或者 document.location 的简写模式。

在这里插入图片描述

让我们来看看 location 有哪些常用属性:

以 url 地址:http://localhost:8080/#/about?name=she&age=16 示例:

属性解释
hash设置或返回从#开始的锚点信息#/about?name=she&age=16
host设置或返回主机名+端口号localhost:8080
hostname设置或返回主机名localhost
port设置或返回端口号8080
href设置或返回完整的 URLhttp://localhost:8080/#/about?name=she&age=16
origin设置或返回协议+主机+端口http://localhost:8080
pathname设置或返回当前 URL 的路径/(hash 值不算在路径里面,此处返回的是#之前的斜杠)
protocol设置或返回当前协议http:
search设置或返回从?开始的查询字符串?name=she&age=16

location 常用方法:

方法名解释语法
assign()加载并显示指定的 URL 的内容location.assign(url);
reload()刷新当前页面,就像刷新按钮一样location.reload();
replace()以给定的 URL 来替换当前的资源location.replace(url);

调用 location.replace() 方法后,当前页面不会保存到会话历史中(session History),这样,用户点击回退按钮时,将不会再跳转到该页面。

在这里插入图片描述

3、window.onhashchange 事件

当 URL 的片段标识符(hash 值)更改时,将触发 hashchange 事件 (跟在#符号后面的 URL 部分,包括#符号)。

  • 使用 addEventListener 监听 hashchange 事件:

    window.addEventListener('hashchange', function() {
      console.log('hash值被修改了')
    }, false);
    
  • 使用 onhashchange 事件处理程序

    function locationHashChanged() {
    	if (location.hash === '#/about') {
    		console.log("欢迎进入about页面");
    	}
    }
    window.onhashchange = locationHashChanged;
    

测试 hashchage 事件:

window.addEventListener('hashchange', function () {
	console.log('hashchage 事件被触发了');
});
// hash值的改变也会触发 window.onpopstate事件,onpopstate事件在 history模式中再做介绍
window.addEventListener("popstate", () => {
	console.log("popstate 事件被触发了");
})

在这里插入图片描述

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

重新获取 hash 值:

在这里插入图片描述

二、history 模式

1、history 定义

history 是 HTML5 提供的新特性,允许开发者直接更改前端路由,也就是更改 url 地址而无需向后端发送 http 请求。

history 是 window.history 的简写模式,是 History 构造函数的实例化对象。

History 接口允许操作浏览器的曾经在标签页或者框架里访问的会话历史记录。

也就是说 History 里面保存着当前标签页的所有浏览页面的访问记录

2、history API

  1. 实例化对象属性

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

    方法名解释语法
    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]);
  3. history.pushState()的使用

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

    • state:一个对象,popState 事件触发时,state 对象会传入回调函数。如无需传参,则设置为 null

    • title:新页面的标题,但是所有浏览器目前都忽略这个值,因此可以设置为空字符串 "" 或者 null

    • url:新的网址地址,必须与当前页面处于同一个域下,浏览器的地址栏将显示这个网址。

      接下来做一个测试,有一个 a.html 页面:
      在这里插入图片描述

      使用 pushState 方法添加一条记录到 History 会话历史中,并传参:
      在这里插入图片描述
      使用 pushState 添加一条记录后,url 地址更新,但是页面并没有更新,也就是说 pushState 方法只是更新了 url 地址
      使用 length 以及 state 查看:
      在这里插入图片描述

  4. 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
    在这里插入图片描述

3、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 / {
	    root  'E:\dist';
	    index  /index.html;
	    try_files $uri $uri/ /index.html;
	}
}

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

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

相关文章

屌的一批,阿里P8推荐的Spring Cloud实战笔记

Spring Cloud 前世今生 Spring Cloud体系由Spring 在2015年年初推出,至今已经五年多,其子项目在不断增加与完善,其所包含的功能点已经基本满足整个微服务体系的需求。加上Spring本身强大的技术后盾和活跃的技术社区氛围,Spring C…

车载毫米波雷达中国市场有望在2025年实现30亿美元的市场规模

近日,专注于前沿科技领域的国际咨询机构ICV发布了全球车载毫米波雷达的市场研究报告,汽车毫米波(mmWave)雷达基于频率为77 GHz的电磁波,具有高精度和准确性,可用于目标检测。这种技术有着广泛的应用&#x…

解决方案丨票据集中在集团总部处理,如何解决实物票据管理难?

目前越来越多的企业都成立了财务共享中心,通过统一财务中心可以进行集中式、标准化、统一化管理,提升财务运营水平与效率、降低企业的整体运作成本、集团战略发展支撑。 如何确保财务共享中心稳健和高效运营,是很多企业建立共享中心后面的难…

【Leetcode每日一刷】动态规划:931. 下降路径最小和

博主简介:努力学习的22级计科生博主主页: 是瑶瑶子啦所属专栏: LeetCode每日一题–进击大厂 目录 一、动态规划套路二、分析1、dp数组含义2、确定递推公式(递推函数的实现)3、dp数组初始化(base case)4、遍历顺序 解题…

React面向组件编程

React面向组件编程 基本理解和使用组件三大核心属性1: state效果理解强烈注意 组件三大核心属性2: props效果理解作用编码操作 组件三大核心属性3: refs与事件处理效果理解编码2.4.4. 事件处理 收集表单数据效果理解 组件的生命周期(重要)效果理解生命周期流程图(旧…

《庖丁解牛Linux内核分析》课后实验:实验一:反汇编分析

实验内容 参照第 1.3 节,将如下 C 语言代码汇编成“.s”文件,并分析“.s”文件中的汇编代码 的执行过程,其中重点关注 EBP/ESP 寄存器、EAX 寄存器、EIP 寄存器和函数调用堆栈空 间在汇编代码的执行过程是如何变化的。 int g(int x) { return…

省钱!NewBing硬核新玩法;手把手教你训练AI模特;用AI替代同事的指南;B站最易上手AI绘画教程 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 『NewBing 的2种硬核新用法』阅读文档并回答问题 & AI绘图 社区同学分享了两种NewBing的新用法,不仅准确高效&#x…

2023年湖北省武汉安全员ABC报名时间考试通过率如何?启程别

2023年湖北省武汉安全员ABC报名时间考试通过率如何?启程别 都2023年了,建筑企业想要报考三类人员,不知道在哪里报名,具备什么样的条件才可以报考建筑安全员abc,什么时间报名考试等等一系列问题,启程别来给你们细细说明…

即时通讯源码自己开发好还是对接云服务好

随着科技的飞速发展,通信技术也日新月异。与此同时,即时通讯应用也越来越受欢迎。许多企业在构建应用程序时会遇到一个问题:使用即时通讯源码自己开发好还是对接云服务好?本文将探讨这两种方法的优缺点,并为您提供一些…

环境配置 | Win10 VSCode连接远程服务器里的docker容器

环境:win10, VS code, 远程服务器Ubuntu16.04(远程服务器上已经安装好了dockers), 1.VScode下载 网址:Download Visual Studio Code - Mac, Linux, Windows 下载后双击运行 2.VSCode上配置 STEP 1.点击vscode右边工具栏点击拓展…

《嵌入式系统的WEB开发》

硬件平台:RK1109/T31/RK3308 软件系统:Linux,Lighttpd/ Nginx, FCGI, HTML/JS 选择使用FCGI,除了使用C 开发调用系统资源方便外. FCGI 可以解决CGI 多入口的问题,统一的入口,对数据同步,都是比…

Python 基于 Django 的学生成绩管理系统,可视化界面(附源码,教程)

1简介 对于学生成绩管理系统,充分运用现代化的信息技术手段,对于学生成绩信息管理发展的趋势就是信息化,信息化时代下的信息管理,需要深化信息管理体制与手段的改革,充分运用信息化手段来全方位的进行学生成绩管理系统…

VTK交互功能-callback/observe模式-vtkCommand

前言:本博文为系列博文,尝试将vtk交互功能讲清楚,包括常用的接口分析、常用的交互逻辑以及常用的交互Widget。若各位小伙伴有需要请多多关注,也希望能给各位小伙伴有所帮助。vtkCommand作为callback/obseve交互模式的基类&#xf…

0201自动配置类的导入-自动装配原理-springboot2.7.x系列

1简介 Spring Boot是基于Spring框架的,它的原理也是基于Spring框架的。 Spring框架是一个非常强大的框架,它提供了一系列的模块来帮助开发人员构建企业级的应用程序。Spring框架的核心是控制反转(Inversion of Control,IoC&…

大数据技术之Spark Streaming概述

前言 数据处理延迟的长短 实时数据处理:毫秒级别离线数据处理:小时 or 天 数据处理的方式 流式(streaming)数据处理批量(batch)数据处理 spark Streaming也是基于sparkCore,所以底层的核心没有变…

FreeRTOS系统学习第一步:新建 FreeRTOS 工程—软件仿真

创建一个FreeRTOS系统工程 1.新建工程文件夹2.Keil新建工程2.1 New Project2.2 Select Device For Target2.3 Manage Run-Time Environment 3. 在 KEIL 工程里面新建文件组3.1在 KEIL 工程里面添加文件 4. 编写 main 函数5. 调试配置5.1 设置软件仿真5.2 修改时钟大小在时钟相关…

你是否线上有使用ThreadLocal,如果结合多线程,请慎用

随着业务的增加,数据量的增加,多线程的使用会越来越频繁,提升单机的处理能力。 前些日子我们线上出现了一个比较严重的故障,这个故障是多线程使用不当引起的,挺有代表性的,所以分享给大家,希望…

前端学习笔记:CSS的引入,元素选择器

这是本人学习的总结,主要学习资料如下 马士兵教育 目录 1、引入CSS1.1、引入CSS的方式1.2、优先级 2、元素选择器2.1、基本选择器2.1.1、选择器2.1.2、优先级 2.2、关系选择器2.2.1、优先级 2.3、属性选择器2.4、伪类选择器 1、引入CSS 1.1、引入CSS的方式 第一个…

互斥锁深度理解与使用

大家好,我是易安! 我们知道一个或者多个操作在CPU执行的过程中不被中断的特性,称为“原子性”。理解这个特性有助于你分析并发编程Bug出现的原因,例如利用它可以分析出long型变量在32位机器上读写可能出现的诡异Bug,明明已经把变量…

SpringCloud--gateway 网关

在Spring Cloud中,使用Gateway网关访问服务可以有多种好处,包括但不限于以下几点: 统一入口管理:Gateway作为统一的服务入口,可以对所有的请求进行统一管理和控制,实现微服务集中管理。 动态路由&#xff…