点击浏览器前进/后退时页面不刷新的兼容解决方案 |
您所在的位置:网站首页 › js获取浏览器访问历史 › 点击浏览器前进/后退时页面不刷新的兼容解决方案 |
问题现象
在业务场景中会出现类似需求,一进入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 |