一些浏览器中返回按钮是直接使用缓存的,不会执行任何js代码,例如, 在提交的时候将按钮设置为loading状态,如果在提交成功后没有对按钮进行处理,那么返回后按钮依然是loading状态,这就很尴尬了尴尬。
原因:部分浏览器在后退时不会触发onload事件,這是HTML5世代浏览器新增的特性之一——Back-Forward Cache(简称bfcache)
什么是bfcache
《JavaScript高级程序设计》有提及bfcache:
bfcache,即back-forward
cache,可称为“往返缓存”,可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存不仅保存页面数据,还保存了DOM和JS的状态,实际上是将整个页面都保存在内存里。如果页面位于bfcache中,那么再次打开该页面就不会触发onload事件
pageshow事件
这个事件在页面显示时触发,无论页面是否来自bfcache。在重新加载的页面中,pageshow会在load事件触发后触发;
而对于bfcache中的页面,pageshow会在页面状态完全恢复的那一刻触发。
pagehide事件
该事件会在浏览器卸载页面的时候触发,而且是在unload事件之前触发。
persisted属性
pageshow事件和pagehide事件的event对象还包含一个名为persisted的布尔值属性。
对于pageshow事件,如果页面是从bfcache中加载的,则这个属性的值为true;否则,这个属性的值为false。
对于pagehide事件,如果页面在卸载之后被保存在bfcache中,则这个属性的值为true;否则,这个属性的值为false。
不同的浏览器在浏览器会在当前窗口“打开”历史纪录中的前一个页面的表现上并不统一,这和浏览器的实现以及页面本身的设置都有关系。
解决方案
Firefox的开发者文档中提供了一些思路:
页面监听了 unload 或者 beforeunload 事件;
页面设置了 “cache-control: no-store”.
网站使用 HTTPS 同时页面至少满足以下一个条件:
“Cache-Control: no-cache”
“Pragma: no-cache”
设置请求头 “Expires: 0” 或者 “Expires” 的值为 “Date” 之前的值 (除非 “Cache-Control: max-age=” 也被设置了);
页面在用户前进后退的时候还没有完全加载完或者它有正在进行的网络请求,比如 XMLHttpRequest;
页面正在进行IndexedDB操作;
顶层的页面包含有frame,并且这些frame由于这里列的任何一条原因而不能被缓存;
页面在一个frame内,并且用户在这个frame内跳转到了一个新的网页,这里将被缓存的是新载入的网页
JS监听pageshow事件阻止页面进入bfcache(个人表示使用此方法)
window.addEventListener('pageshow', function( e ){
if (e.persisted) {
window.location.reload()
}
})
Safari、UC、qq浏览器测试通过。但是UC、qq浏览器会先闪过bfcache中的页面,因为pageshow是在load事件触发之后才触发的。browser依然会保留红色,我认为是因为browser回到上页时不触发任何事件。
JS监听pagehide事件阻止页面进入bfcache
window.addEventListener('pagehide', function(e) {
var $body = $(document.body);
$body.children().remove();
// 要等到回调函数完成,用户按返回才执行script标签的代码
setTimeout(function() {
$body.append("<script type='text/javascript'>window.location.reload();<\/script>");
});
});
Safari、UC、qq浏览器测试通过。browser依然会保留红色,我认为是因为browser回到上页时不触发任何事件。