前端路由实现:通过onpopstate()监控浏览器前进后退数据
发布于 作者:苏南大叔 来源:程序如此灵动~
苏南大叔在上一篇文字中,讲述了window.history.对象上的pushState(),这个函数可以在改变url的同时,保存一些state数据,以及一个不知道做啥的title数据。那么,如何读取出这些保存好的state数据呢?这就是本文中苏南大叔所讲述的内容:window.history.对象上的popState行为。

本文测试环境:mac,chrome@73.0.3683.103。
不存在popState()方法
这个window.history.对象上的popState行为,是非常的不按常理出牌。所以,理解上需要大家发挥一点想象力。push和pop都是典型的堆栈操作,而pushState()方法的存在,并不能推断出popState()方法的存在。事实上,直接调用这个想象中的popState()方法的话,就会有如下报错信息显示:
Uncaught TypeError: window.history.popState is not a function截图如下:

存在popState事件
但是,堆栈有push必定有pop,所以,苏南大叔认为:popstate事件是必然存在的,可能就是不存在公开的popState()方法罢了,比如:popState()可能是个私有的方法。
苏南大叔提示您:可以通过window.onpopstate来感知到popState事件。
下面来引用一些官方的文字描述:
每当处于激活状态的历史记录条目发生变化时,popstate事件就会在对应window对象上触发. 如果当前处于激活状态的历史记录条目是由history.pushState()方法创建,或者由history.replaceState()方法修改过的, 则popstate事件对象的state属性包含了这个历史记录条目的state对象的一个拷贝.
如何触发popState事件
调用history.pushState()或者history.replaceState()不会触发popstate事件. popstate事件只会在浏览器某些行为下触发, 比如:
- 用户主动触发的:点击后退、前进按钮。
- 程序猿主动触发:在
JavaScript中调用history.back()、history.forward()、history.go()方法。
onpopstate的使用姿势
在onpopstate里面:
- 可以获得
event.state数据,这个数据是pushState()或者replaceState()的第一个参数存进去的。 - 而关于第二个参数
title,请注意:对于onpopstate来说,不存在的数据。 - 第三个参数
url,可以通过document.location直接读取。
下面的是几个使用范例:
window.onpopstate = function(event) {
alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};或者省略window.字样:
onpopstate = function(event) {
alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};或者:
window.addEventListener("popstate", function(event) {
console.log(event);
}, false); event里面,该有的数据是没用,却存在着很多没用的数据。这个是有些奇怪。比如,您可以检查一下下面的对象,还是会有额外的收获的,具体的宝藏内容,大家可以自行查找:
console.log(event.currentTarget.clientInformation);
console.log(event.document);查看当前页面的state
如果不监控onpopstate事件,可以通过如下方法获得当前页面的state数据:
window.history.state
相关文章
总结
本文中的popstate和上文中的pushstate加以组合,就是很多前端框架中的路由原理基础之一。至于popstate字符中的大小写问题,个人建议您,还是严格按照demo里面的写法写。这个问题,很难说清楚。有的时候ok,但是有的时候就不行来。严格的来说,js语法是区分大小写的。
本文的popstate和上文中的pushstate,来自h5范畴,所以,在苏南大叔的文章分类里面,也是归属于h5范畴的。有些牵强对吧,不过,暂时想不出更好的分类了。哈哈。