浏览器上的window.history就是记录页面的历史记录的,在浏览器上打印history对象,会有如下:
History {pushState: ƒ, replaceState: ƒ, length: 7, scrollRestoration: "auto", state: null}
history.length
length
是指当前浏览过多少个页面,无论你是执行后退还是前进一页,history都是不变的,除非在当前页面新打开一个链接,那么history就会加一。
history.pushState
history.pushState(State,Title,Url),不跳转,新增一条历史记录,当前页面的url会变成Url,但是不会刷新当前页面,如果此时新打开一个页面,后退会去到Url链接,但页面内容还是url的内容,再后退就会去到url链接,内容不变,就是url的内容。
需要注意的是,history.pushState的Url不能跨域
,否则会报错。
history.replaceState
history..replaceState(State,Title,Url),不跳转,修改浏览历史中当前纪录,当前页面url的历史记录会被替换成指定的Url,当前页面的url会变成Url,直接替换掉原来的url,相当于原来的url已经不存在,但是不会刷新当前页面,如果此时新打开一个页面,后退会去到Url链接,但页面内容会改变成Url的内容,再后退就没有可后退的链接了。
需要注意的是,history.replaceState的Url不能跨域
,否则会报错。
location.replace
location.replace(url) 会跳转至指定页面,当前页面url的历史记录不会保留,相当于替换了当前的历史记录
location.href
location.href:跳转至指定页面,当前页面url的历史记录会保留
window.onpopstate
每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。使用的时候,可以为popstate事件指定回调函数。这个回调函数的参数是一个event事件对象,它的state属性指向pushState和replaceState方法为当前URL所提供的状态对象(即这两个方法的第一个参数state)。如:
history.pushState({title:"login"}, "login", "/login");
window.onpopstate = function (event) {
if(event.state) {
var state = event.state.title;
switch(state) {
case "login":.............;break;
case "join" :.............;break;
}
}
};
// 或者
window.addEventListener("popstate", function(event){
if(event.state) {
var state = event.state.title;
switch(state) {
case "login":.............;break;
case "join" :.............;break;
}
}
}, false);
上面代码中的event.state,就是通过pushState和replaceState方法,为当前URL绑定的state对象。这个state对象也可以直接通过history对象读取history.state。
实践
最近做的一个需求是这样的:先由中转页a跳去目标页面b,按回退按钮,跳去中间后台配置页面b1,再按回退按钮跳去中间后台配置页面b2,以此下去,只到跳转完所有后台配置的页面,最终跳回目标页面b,再按返回退出所有页面。
用history来解释的话就是:
a->b->back->a->b1->back->b2->...->back->b->back->退出
用上面的知识来解决就是
a->b,在a页面,获取跳转url的b页面链接,替换参数,改变a链接成a*,即将a的历史记录修改成a*,执行
history.replaceState(null, document.title, a*);window.location.href = b;
回退,此时到a*,获取后台配置,执行
window.location.href = b1;
回退,此时到a*,获取后台配置,执行
window.location.href = b2;
....
后退回到a*,最后回到b,执行
window.location.replace(b);
再后退,退出页面
以上就是利用history和location解决的一个简单示例,其他的应用还可以是改变一个页面的url而不用刷新页面等。
外篇
pageshow
和 pagehide
事件
手机上的浏览器有一个特性,名叫“往返缓存”(back-forward cache,或bfcache),可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。如果页面位于bfcache中,那么再次打开该页面就不会触发load事件。尽管由于内存中保存了整个页面的状态,不触发load事件也不应该会导致什么问题,但为了更形象地说明bfcache的行为,Firefox还是提供了一些新事件。 第一个事件就是pageshow
,这个事件在页面显示时触发,无论页面是否来自bfcache。在重新加载页面中,pageshow会在load事件触发后触发;而对于bfcache中的页面,pageshow会在页面状态完全恢复的那一刻触发。
1)load 和 unload 事件监听web页面的进入和离开,一般用于页面的首次加载、刷新和关闭等操作的监听;
2)pageshow
和 pagehide
事件多用于监听浏览器的前进和后退等。
pageshow和load区别:
pageshow 事件类似于 load 事件,load 事件在页面第一次加载时触发, pageshow 事件在每次加载页面时触发,即 load 事件在页面从浏览器缓存中读取时不触发。
一般情况下,移动端浏览器会将当前已访问页面存入缓存中,缓存中保存着页面数据,DOM和js的状态,前进和后退操作时直接从浏览器缓存中读取页面内容,而不进行页面刷新,所以监听前进和后退操作时可用pageshow事件。
window.performance
对象
performance.navigation.type
是一个无符号短整型,接口呈现了如何导航到当前文档的信息。它有四种type类型:
1、TYPE_NAVIGATE (0)
:当前页面是通过点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址,type值为0。
2、TYPE_RELOAD (1)
:点击刷新页面按钮或者通过Location.reload()方法显示的页面,type值为1:。
3、TYPE_BACK_FORWARD (2)
:页面通过历史记录和前进后退访问时。type值为2。
4、TYPE_RESERVED (255)
: 任何其他方式,type值为255。
所以type为2可以作为页面后退或者前进时的一个判断依据。
window.addEventListener('pageshow', (e) => {
if (e.persisted || (window.performance && window.performance.navigation.type == 2)) {
// 页面后退或者前进时刷新页面
location.reload()
}