浅谈history对象以及路由插件原理
简介
History对象最初设计用来表示窗口的浏览历史,但是,出于隐私方面的原因,History对象不再允许脚本访问已经访问过的实际URL。虽然,我们不清楚历史URL,但是,我们可以通过History对象的内置属性方法进行跳转。
对象属性
length
该属性代表着浏览器历史列表中的URL数量。初始值为1,如果当前窗口先后访问了两个网址,那该属性的值变为2。
history.length // 1
// 访问了一个新的URL
history.length // 2
state
HTML5新增属性,返回一个表示历史堆栈顶部的状态的值,这是一种可以不必等待popstate
事件而查看状态的方式。
scrollRestoration
允许Web应用程序在历史导航上显式地设置默认滚动恢复行为。此属性可以是自动的(auto)或者手动的(manual)。
对象方法
go方法
go
方法是History对象三个方法中的核心方法,通过go
方法可以完美替代其他的两个方法。该方法接收一个可选参数,这个参数可以是number
也可以是URL
。
ps:经过多次试验,传入URL
参数貌似没有作用,有待后续研究
当使用number
参数时,页面会跳转到History的URL列表的相对位置。比如当传入参数为-1
,则相当于点击浏览器后退按钮的效果;当传入参数为1
时,相当于点击浏览器前进按钮;当不传参数或者传入参数为0
时,页面会刷新。
window.history.go(-1) // 后退
window.history.go(1) // 前进
window.history.go(0) // 刷新
window.history.go() // 刷新
tips:当传入的number
对应的位置没有URL,则该条语句会静默失败
forward方法
forward
方法可以加载历史列表中的下一个URL,类似于go(1)
,实现了点击浏览器前进按钮的效果。
window.history.forward() // 前进
window.history.go(1) // 前进
back方法
back
方法可以加载历史列表中的上一个URL,类似于go(-1)
,实现了点击浏览器后退按钮的效果。
window.history.back() // 后退
window.history.go(-1) // 后退
tips:当URL队列中没有上一个URL时,back
方法会失效;同理,当URL队列中没有下一个URL时,forward
方法会失效。
HTML5新增方法
HTML5为History对象添加了两个新方法,pushState
和replaceState
方法,用来在浏览历史中添加和修改记录。
pushState方法
pushState
方法接收三个参数:
- state:一个与指定网址相关的状态对象,
popstate
事件触发时,该对象会传入回调函数。如果不需要这个对象(即不需要传参),可以设为null
- title:新页面的标题,但是大部分浏览器目前都忽略这个值,所以这里也可以设为
null
- url:新的网址,必须与当前页处在同一域,浏览器的地址栏将显示这个网址
比如当前的网址是localhost:63342/1.html
,使用pushState
方法在浏览记录中可以添加一条新的记录:
window.history.pushState({params: 'aaa'}, null, '2.html')
输入这行语句后,浏览器地址栏中的URL变为了localhost:63342/2.html
,但是无论这是不是一个真实网址,它都不会跳转,这只是一条历史记录。此时,可以通过state
取到状态。
此时,如果你前往下个地址后点击后退按钮,页面将返回到localhost:63342/2.html
,此时,也可以通过state
属性取到状态。
window.history.state // {params: "aaa"}
tips:如果pushState
的第三个参数是一个跨域网址,控制台会报错,这主要是因为安全问题,防止不法分子伪装URL
window.history.pushState(null, null, 'www.baidu.com') // 报错
replaceState方法
该方法基本和pushState
一致,但是不同的是,该方法会直接替换当前的历史记录。
路由插件的原理
传统的History用法是操纵浏览器进行前进或后退的跳转,用处不是很大。但是,HTML5新增的方法为其带来了脱胎换骨的变化。
众所周知,vue-router等一众路由插件实现的功能是更新页面的视图,但是却不重新请求页面,也就是说,其实,他们并没有实际进行了跳转,而是修改了页面的DOM并通过修改页面的URL来模拟跳转。
在HTML5之前,页面路由只有hash模式,而HTML5中History对象的新增方法,带来了另一种模式:history模式。
hash模式
在HTML5之前,vue-router是通过修改URL的hash
值(URL中#
开始的字符串,不了解的同学可以看我的上一篇文章)来达到修改页面URL并生成历史记录,但却不会重新请求页面。所以,不使用vue-router中history
模式的情况下,你会发现你的路径前总会有一个#
。
比如,你在vue-router中设置的路径是/b
,在你的想象中,路径应该是http://localhost:8080/b
,但是,现实很骨感,实际路径是:http://localhost:8080/#/b
,原因就是因为没开启history
模式的情况下,vue-router是通过hashchange
事件来监听URL中hash的改变并通过修改hash来模拟路径的变化。
由于通过window.location.hash
修改hash是会有历史记录产生的,所以,在SPA中,依然可以通过后退、前进按钮来控制路由的跳转。
hash模式最大的优点是兼容性强,可以兼容一众老式浏览器。而它最大的缺点是,页面URL中一直挂着一个难看的#
,这一点连vue-router的官网也对其进行了吐槽。
有需求就有功能,所以,当HTML5发布后,又有了history模式。
history模式
看到这里,如果认真看了pushState
方法的同学应该已经差不多明白了,vue-router的history模式就是通过HTML5中History对象的pushState
方法进行模拟的。
当vue-router每次需要跳转页面时,页面DOM的修改方式和时机并没有改变,和hash模式一样。但是,修改URL的方式改变了。此时,有了pushState
方法,可以不用修改丑陋的hash模拟而是直接在历史记录中添加一条新的URL。
那么,没有了hash,如何监听URL的改变呢?HTML5还提供了一个popstate
事件,当用户点击前进、后退按钮,或者调用back
、forward
、go
方法时触发,可以监听URL的改变。
在这里提一句,使用history模式,就连路由传值都有更好的方式——使用pushState
的第一个参数进行传值,使用History的state
属性进行取值。
当使用了history模式时,使用vue-router跳入/b
时,此时的页面URL不是丑陋的http://localhost:8080/#/b
,而是预料之中的http://localhost:8080/b
。
// hash模式
window.location.href // http://localhost:8080/#/b
// history
window.location.href // http://localhost:8080/b
总结
虽然,history模式提供了完美的URL显示,但是,正所谓鱼和熊掌不可兼得,兼容性和美观也不可兼得。只有兼容了HTML5的浏览器(IE10+)才能使用history模式,不然,就老实的继续使用hash模式吧。
所以,使用何种模式,还是取决于软件的兼容性,如果不需要兼容低级浏览器,那就放心大胆的使用history模式吧!
浅谈history对象以及路由插件原理的更多相关文章
- 【ASP.NET MVC系列】浅谈ASP.NET MVC 路由
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- 浅谈Eclipse调用Tomcat服务的原理
浅谈Eclipse调用Tomcat服务的原理 转:http://www.thinksaas.cn/group/topic/341645/ 转:http://www.173it.cn/Html/?581 ...
- 再谈js对象数据结构底层实现原理-object array map set
如果有java基础的同学,可以回顾下<再谈Java数据结构—分析底层实现与应用注意事项>:java把内存分两种:一种是栈内存,另一种是堆内存.基本类型(即int,short,long,by ...
- python学习(28) 浅谈可变对象的单例模式设计
python开发,有时候需要设计单例模式保证操作的唯一性和安全性.理论上python语言底层实现和C/C++不同,python采取的是引用模式,当一个对象是可变对象,对其修改不会更改引用的指向,当一个 ...
- 浅谈 js 对象 toJSON 方法
前些天在<浅谈 JSON.stringify 方法>说了他的正确使用姿势,今天来说下 toJSON 方法吧.其实我觉得这货跟 toString 一个道理,他是给 stringify 方法字 ...
- 浅谈location对象
简介 Location 对象存储在 Window 对象的 Location 属性中,表示那个窗口中当前显示的文档的 Web 地址.通过Location对象,可以获取URL中的各项信息,调用对象方法也可 ...
- 浅谈Qt事件的路由机制:鼠标事件
请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正. 这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键 ...
- JS核心系列:浅谈原型对象和原型链
在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...
- 浅谈Js对象的概念、创建、调用、删除、修改!
一.我们经常困惑,对象究竟是什么,其实这是一种思维,一种意识上的东西,就像我们都说 世界是有物质组成的道理一样,理解了下面的几句话!对象也不是那么抽象! 1.javascript中的所有事 ...
随机推荐
- Mybatis中的if test 标签
<if test='patrolResult != null and patrolResult != "" and patrolResult !="1"' ...
- memcached与redis实现的对比
版权声明:本文由田京昆原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/129 来源:腾云阁 https://www.qclo ...
- 腾讯云CMQ消息队列在Linux环境下的使用
版权声明:本文由李少华原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/76 来源:腾云阁 https://www.qclou ...
- codereviw得到的一些经验
1.设置display为none的元素,它的背景图依然会被下载.所以最好是等到该元素需要显示时才给他加上相应的有背景图的class. 2.css中虽然ID选择器的优先级比较高,效率也比较高,但灵活性差 ...
- 【BZOJ2957】楼房重建 分块
[BZOJ2957]楼房重建 Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子 ...
- [IIS] IIS Framework "aspnet_regiis.exe" 注册
Error:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“
- web.xml的contextConfigLocation作用及自动加载applicationContext.xml
web.xml的contextConfigLocation作用及自动加载applicationContext.xml 转自:http://blog.csdn.net/sapphire_aling/ar ...
- 170509、文本编辑器编写的shell脚本在linux下无法执行的解决方法
今天碰到一个奇怪的问题,编写好的shell脚本再linux上执行一直提示找不到文件或目录,后来想想是文本编辑器的问题,记录下来!!! 1.查看当前文本格式 Notepad++界面中,在右下角有文件格式 ...
- CentOS7使用yum安装nginx
CentOS默认没有nginx的yum源需要yum安装nginx可以使用一下方法 一,环境检测 二,设置yum源 rpm -Uvh http://nginx.org/packages/centos/7 ...
- ArcGIS for Server的安装及站点中的集群配置 分类: ArcGIS for server 2015-07-18 14:14 16人阅读 评论(0) 收藏
坚信并为之坚持是一切希望的原因. (不足之处,欢迎批评指正!) --------------------环境:Windows server2008R2虚拟机两台----------------- ...