bfcache相关 pageshow事件
发布网友
发布时间:2024-10-04 07:28
我来回答
共1个回答
热心网友
时间:2024-10-10 10:40
让我们探讨一种情况:在列表页面中,预期每次网页加载后,onload()事件都会以ajax方式重新获取最新的列表数据。因此,点击后退至该页面时,用户应该能立即看到最新的列表资料。然而,在某些浏览器中,回到上一页时不会自动加载更新后的资料,需要刷新才能重新加载。这是因为部分浏览器在后退时不会触发onload事件,这是HTML5时代浏览器新增的功能之一——Back-Forward Cache(简称bfcache)。
什么是bfcache?
熟知的《JavaScript高级程序设计》一书中提到了bfcache:bfcache,也称为“往返缓存”,可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存不仅保存页面数据,还保存了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。
不同的浏览器在处理当前窗口打开历史记录中的前一个页面时并不统一,这与浏览器的实现和页面本身的设置有关。
测试
测试代码和线上示例已提供,这里不再赘述。
测试结果表明,Safari、Firefox、UC、qq浏览器、browser都有bfcache功能。回到上页时,Safari、UC和qq浏览器不会触发load事件;IE、Firefox、Chrome和Opera支持pageshow事件,但会触发load事件;browser不触发任何事件。
解决方案
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内跳转到了一个新的网页,这里将被缓存的是新载入的网页。
监听pageshow事件阻止页面进入bfcache
一言不合放代码
window.addEventListener('pageshow', function(e) {
if (e.persisted) {
window.location.reload()
})
Safari、UC、qq浏览器测试通过。但是,UC、qq浏览器会先闪过bfcache中的页面,因为pageshow事件在load事件触发之后才触发。browser依然会保留红色,我认为是因为browser回到上页时不触发任何事件。
监听pagehide事件阻止页面进入bfcache
一言不合放代码
window.addEventListener('pagehide', function(e) {
var $body = $(document.body);
$body.children().remove();
// 要等到回调函数完成,用户按返回才执行script标签的代码
setTimeout(function() {
$body.append("")
总结
对于PC浏览器,设置禁用页面缓存的header即可实现后退刷新。对于支持bfcache/page cache的移动端浏览器,可以通过JS监听pageshow/pagehide,在检测到后退时强制刷新。在前两个方案都无效的情况下,可以在HTML中写入服务端页面生成版本号,与本地存储中的版本号对比判断是否发生了后退并使用缓存中的页面。
原文链接:(链接省略,实际使用时应提供原文链接)