点击浏览器前进/后退时页面不刷新的兼容解决方案

您所在的位置:网站首页 js获取浏览器访问历史 点击浏览器前进/后退时页面不刷新的兼容解决方案

点击浏览器前进/后退时页面不刷新的兼容解决方案

2023-08-13 21:26| 来源: 网络整理| 查看: 265

问题现象

在业务场景中会出现类似需求,一进入a页面就发起请求对用户身份进行判断,如果该用户不满足操作页面的条件,则给出弹窗提示后跳转到登录页面b。到b页面后,再点击浏览器后退按钮回到a页面,发现a页面并没有刷新reload执行js,导致并没有再对用户身份的判断给出提示。

点击浏览器前进/后退按钮没有重新执行js的原因 一、back-forward cache(往返缓存)

bfcache是为了让用户在使用浏览器前进/后退按钮时拥有更加流畅体验的一种策略。这是一种较强的缓存策略,在点击浏览器前进/后退时DOM,window,js对象,xhr都有可能被缓存,但不同浏览器的缓存策略不一致。直到用户关闭浏览器,缓存状态才会被清除。

pageShow

对于应用bfcache策略的浏览器,如果想在页面重新从缓存中加载后定义一些行为的,可以使用pageshow事件(IE不支持)。当一条会话历史记录被执行的时候将会触发页面显示(pageshow)事件,无论是否来自缓存。

pageShow事件与onload事件类似,一般来说

在页面第一次加载时:会先后触发onload和pageShow; 从其他页面点击浏览器返回按钮:onload不一定被触发(桌面端chrome会触发onload),pageShow大概率会被触发(Chrome, FireFox, Safari)

判断是否是来自缓存的页面:

e.persisted: 可以根据pageShow事件对象中的e.persisted判断该页面是否来自缓存中,返回值为bool,为true则表示来自缓存中的数据。但不同浏览器e.persisted的表现不同,仅依赖e.persisted是不可靠的。

window.performance.navigation.type === 2: performance.navigation对象的type字段有以下情况:

0: 点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址 1: 点击刷新页面按钮或者通过Location.reload()方法 2: 页面通过历史记录和前进后退访问 255: 任何其他方式 但这种判断方式,是将被废弃的Navigation Timing Level 1标准中的window.performance.navigation对象才包含type字段。建议使用Navigation Timing Level 2中window.performance.getEntriesByType("navigation")[0].type判断

window.performance.getEntriesByType("navigation")[0].type === 'back_forward': 其中type字段有以下情况:

'navigate': 点击链接,书签和表单提交,或者脚本操作,或者在url中直接输入地址 'reload': 点击刷新页面按钮或者通过Location.reload()方法 'back_forward': 页面通过历史记录和前进后退访问 'prerender': 由prerender link导航而来

综上,可得到以下pageShow的监听,解决ios的bfcache问题

window.addEventListener('pageshow', function (event) { if (event.persisted || (window.performance && window.performance.getEntriesByType && String(window.performance.getEntriesByType('navigation')[0].type) === 'back_forward')) { location.reload(); } } 复制代码 二、部分安卓浏览器的前进/后退不是使用bfcache策略加速页面展示

对于使用bfcache策略的浏览器可通过pageShow监听非初始化加载的操作,但有些安卓浏览器(如小米自带、uc、qq等部分版本浏览器)没有使用bfcache策略,而是将页面封装成类似webView的形式,对于这种情况,可通过visibilitychange事件判断是否为初始化加载。

visibilitychange可兼容safari以外的浏览器,在页面可见行发生变化时(如标签页切换显隐),会触发该事件

document.visibilityState有visible/hidden/prerender三种值

hidden:页面彻底不可见 visible:页面至少一部分可见 prerender:页面即将或正在渲染,处于不可见状态

监听如下(出于兼容考虑,在window上挂载监听):

window.addEventListener("visibilitychange", function() { console.log(document.visibilityState); if(document.visibilityState == "hidden") { console.log(‘隐藏‘); } else if (document.visibilityState == "visible") { console.log(‘显示‘) } }); 复制代码 三、总结

对于ios的bfcache可通过pageShow判断页面是否来源于缓存解决,而安卓端可通过监听visibilitychange事件判断页面当前可见性是否变化决定后续操作,基本可兼容大部分机型和场景。

四、通过其他方式避免缓存 cache-control

可对http的请求/响应头的Cache-Control设置禁止缓存:Cache-Control: no-cache, no-store,must-revalidate,强制从服务加载页面。但由于ios支持bfcache,该方法在ios无效,可满足大多数场景。

也可以使用meta标签, 有时chrome等浏览器不支持:

复制代码 随机数

对于请求的缓存,也可以通过随机数(如时间戳"?timestamp=" + new Date().getTime())避免缓存。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3