【Vue】重新理解Vue-Router中的两种路由模式

历史小剧场

唐代实在太高太强了,他们忽忘了民族界限,他们不懂害怕外国人,不懂提防外国人,大量使用外国人当兵作将,结果才弄得不可收拾。于是唐代的府兵一变而成为“藩镇”,军阀割据,胡族临制。----《中国历代政治得失》

location 和 history接口

window.location

说到location对象,它有很多的属性。我们可以通过改变其属性值修改页面的url。我们在单页应用中需要做到的是改变url不刷新页面,location接口提供以下两种方式可以做到:

  1. locaiton.href 赋值时只改变url的hash
  2. 直接赋值location.hash
    在这里插入图片描述

除此之后,还有一个常用方法:location.search(): 会直接刷新页面。

window.history

history 接口 是 HTML5 新增的,它有5个方法可以改变url而不刷新页面。

  1. history.pushSate()
    在这里插入图片描述
  2. history.replaceState()
    在这里插入图片描述
  3. history.forward(). 等价于 history.go(1): 页面前进
  4. history.back() 等价于 history.go(-1): 页面后退

如何监听url的变化

hashchange

hashchange 事件能监听 url hash 的改变

window.addEventListener('hashchange', function(e) {console.log(e)
})
popstate

popstate 事件能监听history.forward() 和 history.back() 方法导致url的变化

window.addEventListener('popstate', (e) => {console.log("state => ", e.state.page)loadHTML(e.state.page, content)
})

hash模式和history模式

前端路由

前端路由是后来发展到SPA(但页面应用)时才出现的概念。SPA就是一个WEB项目只有一个HTML页面,一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转。

优点:前后端的彻底分离,不刷新页面,用户体验较好,页面持久性较好。

hash模式
  • 把前端的路由用#拼接到真实url后面的模式,但是会覆盖锚点定位元素的功能,通过监听URL的哈希部分变化,响应地更新页面的内容
  • 前端路由的处理完全在客户端进行,在路由发生变化时,只会改变URL中的哈希部分(#后面的路径),且不会向服务器发送新的请求,而是触发 hashchange 事件。
  • hash值的改变,都会在浏览器的访问历史中增加一个记录,所以可以通过浏览器的回退、前进按钮控制hash的切换。
  • hash路由不会造成404页面的问题,因为所有路由信息都在客户端进行解析和处理,服务端只负责提供应用的初始HTML页面和静态资源,不需要关心路由的匹配问题。
  • 通过location.hash 修改hash值,触发更新。
  • 通过监听hashchange事件监听浏览器前进或者后退,触发更新

实现

这里有三个文件:一个主页面 hash.html,两个子页面:Home.html 和 About.html

Home.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Home</title>
</head>
<body>Home
</body>
</html>

About.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>About</title>
</head>
<body>About
</body>
</html>

hash.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>哈希路由</title>
</head>
<body><ul><li><a href="Home.html">Home</a></li><li><a href="About.html">About</a></li></ul><div id="content"></div><script>const contentEle = document.querySelector("#content");const ulEle = document.querySelector("ul")const loadHTML = (url, element) => {fetch(url).then(response => {if (response.ok) {return response.text()}throw new Error('Network response was not ok.');}).then(html => {element.innerHTML = html;}).catch(error => {console.error("error => ", error)})}// 页面刷新时,需要重新获取hashwindow.addEventListener('load', () => {// 获取当前的hash值const currentHash = window.location.hash;// 如果存在hash值,执行相应的逻辑if (currentHash) {// 这里可以添加处理hash的逻辑console.log('current hash: ', currentHash.slice(1))loadHTML(currentHash.slice(1), contentEle)}})ulEle.addEventListener('click', (e) => {// 不跳转e.preventDefault()const page = e.target.getAttribute('href')loadHTML(page, contentEle)location.hash = `#${page}`})</script>
</body>
</html>
history 模式
  • 在使用history模式时,需要通过服务端支持允许地址可访问,如果没有设置,就很容易导致404的局面;
  • 改变url:history 提供了 pushState 和 replaceState 两个方法来记录路由状态,这两个方法只改变URL不会引起页面刷新;
  • 监听url变化:通过 popstate 事件监听history 变化,在点击浏览器的前进或者后端功能时触发,在 popstate 事件中根据状态信息加载对应的页面内容

实现

这里有五个文件:主页面一个 history.html; 子页面4个:test1.html、test2.html、test3.html、test4.html

test1.html


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>11111
</body>
</html>

test2.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>2222
</body>
</html>

test3.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>33333
</body>
</html>

test4.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body>4444
</body>
</html>

history.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><button id="pushStateBtn">pushState压栈</button><button id="getLenBtn">getLen</button><button id="replaceStateBtn">replaceState替换</button><button id="forward">前进</button><button id="back">后退</button><div>栈:<span id="size"></span></div><hr><div id="content"></div><script>const loadHTML = (url, element) => {    fetch(url).then(response => {if (response.ok) {return response.text()}throw new Error('Network response was not ok.');}).then(html => {element.innerHTML = html;}).catch(error => {console.error("error => ", error)})}const pushStateBtn = document.getElementById('pushStateBtn');const getLenBtn = document.getElementById('getLenBtn');const size = document.getElementById('size');const replaceStateBtn = document.getElementById('replaceStateBtn');const forward = document.getElementById('forward');const back = document.getElementById('back');const content = document.getElementById('content');let i = 1;size.textContent = `当前历史记录栈总数:${history.length}`;pushStateBtn.addEventListener('click', () => {const page = `test${i}.html`history.pushState({page: page}, "", page)loadHTML(page, content)i++;}, false)getLenBtn.addEventListener('click', () => {size.textContent = `当前历史记录栈总数:${history.length}`;})forward.addEventListener('click', () => history.forward())back.addEventListener('click', () => history.back())window.addEventListener('popstate', (e) => {console.log("state => ", e.state.page)loadHTML(e.state.page, content)})</script>
</body>
</html>

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

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

相关文章

uni-app:踩坑路---scroll-view内使用fixed定位,无效的问题

前言&#xff1a; emmm&#xff0c;说起来这个问题整得还挺好笑的&#xff0c;本人在公司内&#xff0c;奋笔疾书写代码&#xff0c;愉快的提交测试的时候&#xff0c;测试跟我说&#xff0c;在苹果手机上你这个样式有bug&#xff0c;我倒是要看看&#xff0c;是什么bug。 安卓…

vscode 远程 Ubuntu 系统

1、在 Ubuntu 下检查 sshd 守护进程是否开启 ps -aux | grep sshd如果没有开启&#xff0c;请在 Ubuntu 下输入指令安装 sudo apt-get install openssh-server2、首先打开 Windows 下的 vscode&#xff0c;点击左下角图标打开远程窗口 3、打开远程窗口&#xff0c;选择“Con…

【HZHY-AI300G智能盒试用连载体验】在华为IoTDA平台上建立设备

目录 华为IoTDA平台 注册IoTDA实例 创建产品 添加设备 本文首发于&#xff1a;【HZHY-AI300G智能盒试用连载体验】 智能工业互联网网关 - 北京合众恒跃科技有限公司 - 电子技术论坛 - 广受欢迎的专业电子论坛! 在上一篇博文中介绍了如何在HZHY-AI300G智能盒创建南向设备&a…

前端特效动画魔法书:文字渐入效果实现,可做引导页面

前端特效动画魔法书&#xff1a;文字渐入效果实现&#xff0c;可做引导页面 简介 在网页设计的世界中&#xff0c;动画是吸引用户眼球的魔法。Anime.js&#xff0c;一个轻量级且功能强大的JavaScript动画库&#xff0c;是实现这一魔法的完美工具。本文将作为你的技术文档&…

【3D编程技巧】如何用四元数旋转矢量在相机空间进行光照计算

这里介绍一个小TIPS&#xff0c;很久没有这么有成就感了。我以前在学3D数学的时候&#xff0c;书上就有一句话&#xff0c;说你把矢量这些东西用久了&#xff0c;就应该形成一种“直觉”&#xff0c;仿佛这些东西就是你的左右手一样。而这次&#xff0c;我居然真的用“直觉”来…

【开源库学习】libodb库学习(三)

4 查询数据库 如果我们不知道我们正在寻找的对象的标识符&#xff0c;我们可以使用查询在数据库中搜索符合特定条件的对象。ODB查询功能是可选的&#xff0c;我们需要使用--generate-query ODB编译器选项显式请求生成必要的数据库支持代码。 ODB提供了一个灵活的查询API&#x…

复现Android中GridView的bug并解决

几年前的一个bug&#xff0c;GridView的item高度不一致。如下图&#xff1a; 复现bug的代码&#xff1a; import android.os.Bundle; import android.widget.BaseAdapter; import android.widget.GridView; import androidx.appcompat.app.AppCompatActivity; import java.uti…

麻省理工学院 - MIT - 线性代数学习笔记

学习视频地址 文章目录 1.01方程组的几何解释2.02矩阵消元3.03乘法和逆矩阵乘法逆 4.04矩阵A的LU分解5.05转置&#xff0c;置换&#xff0c;向量空间置换转置向量空间 6.06列空间和零空间7.07求解Ax0&#xff1a;主变量&#xff0c;特解 1.01方程组的几何解释 对于二元方程组&…

Scratch自制:《袁坤》游戏攻略

大家好&#xff01;我也是很久没有动静了&#xff0c;这次我又来了&#xff0c;并且还带来了一个用Scratch制作的游戏&#xff0c;大家还记得我很久以前用C制作的《袁坤》吗&#xff1f;&#xff08;详见C自制游戏《袁坤》1.2版本发布&#xff01;-CSDN博客&#xff09;这次它又…

种类并查集

最近玩的太嗨了&#xff0c;都忘了自己还有三篇博客还在拖更&#xff0c;也是今天一更到底好吧&#xff0c;边更新边写题&#xff0c;让看官老爷有更多的样题去联系 引入—— 在学这个之前&#xff0c;我相信各位应该已经接触过了并查集了吧&#xff0c;嗯&#xff1f;什么&a…

Kubernetes 1.24 版弃用 Dockershim 后如何迁移到 containerd 和 CRI-O

在本系列的上一篇文章中&#xff0c;我们讨论了什么是 CRI 和 OCI&#xff0c;Docker、containerd、CRI-O 之间的区别以及它们的架构等。最近&#xff0c;我们得知 Docker 即将从 kubernetes 中弃用&#xff01;&#xff08;查看 kubernetes 官方的这篇文章&#xff09;那么让我…

VSCODE 下 openocd Jlink 的配置笔记

title: VSCODE 下 openocd Jlink 的配置笔记 tags: STM32HalCubemax 文章目录 内容VSCODE 下 openocd Jlink 的配置笔记安装完成后修改jlink的配置文件然后修改你的下载器为jlink烧录你的项目绝对会出现下面的问题那么打开下载的第一个软件 &#xff08;点到这个jlink右键&…

Kafka架构详解之分区Partition

目录 一、简介二、架构三、分区Partition1.分区概念2.Offsets&#xff08;偏移量&#xff09;和消息的顺序3.分区如何为Kafka提供扩展能力4.producer写入策略5.consumer消费机制 一、简介 Apache Kafka 是分布式发布 - 订阅消息系统&#xff0c;在 kafka 官网上对 kafka 的定义…

【11】微服务链路追踪SkyWalking

1、skywalking是什么 1.1 链路追踪介绍 对于一个大型的几十个、几百个微服务构成的微服务架构系统&#xff0c;通常会遇到下面一些问题&#xff0c;比如&#xff1a; 如何串联整个调用链路&#xff0c;快速定位问题&#xff1f;如何缕清各个微服务之间的依赖关系&#xff1f;…

【AI学习】LLaMA 系列模型的进化(二)

在前面LLaMA 系列模型的进化&#xff08;一&#xff09;中学习了LLama模型的总体进化发展&#xff0c;再来看看其中涉及的一些重要技术。 PreLayerNorm Layer Norm有Pre-LN和Post-LN两种。Layer Normalization&#xff08;LN&#xff09;在Transformer架构中的放置位置对模型…

基于PaddleOCR + NLP实现证件识别

基于PaddleOCR NLP实现证件识别 PaddleOCR识别paddleOCR安装安装 anconda虚拟环境(可参考yolov5的安装教程) paddleOCR识别PaddleNLP模型信息抽取paddle打包exe 进行ocr识别 什么是PaddleOCR&#xff1f; PaddleOCR 旨在打造一套丰富、领先、且实用的 OCR 工具库&#xff0c;助…

【HarmonyOS开发】Navigation使用

简介 Navigation是路由容器组件&#xff0c;包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。适用于模块内和跨模块的路由切换。 在页面跳转时&#xff0c;应该使用页面路由router&#xff0c;在页面内的页面跳转时&#xff0c;建议使用Navigation达到更好的转场动效…

Spring Boot集成Spring Batch快速入门Demo

1.什么是Spring Batch&#xff1f; Spring Batch 是一个轻量级的开源框架&#xff0c;它提供了一种简单的方式来处理大量的数据。它基于Spring框架&#xff0c;提供了一套批处理框架&#xff0c;可以处理各种类型的批处理任务&#xff0c;如ETL、数据导入/导出、报表生成等。S…

Armv8/Armv9架构的学习大纲-学习方法-自学路线-付费学习路线

本文给大家列出了Arm架构的学习大纲、学习方法、自学路线、付费学习路线。有兴趣的可以关注&#xff0c;希望对您有帮助。 如果大家有需要的&#xff0c;欢迎关注我的CSDN课程&#xff1a;https://edu.csdn.net/lecturer/6964 ARM 64位架构介绍 ARM 64位架构介绍 ARM架构概况…

uniapp,vue3上传图片组件封装

首先创建一个 components 文件在里面进行组件的创建 下面是 vip组件的封装 也就是图片上传组件 只是我的命名是随便起的 <template><!--图片 --><view class"up-page"><!--图片--><view class"show-box" v-for"(item,ind…