从window.history理解浏览器返回不触发页面刷新问题

一,基础概念

DOM window 对象通过 history 对象提供了对浏览器的会话历史的访问,它暴露了很多有用的方法和属性,允许你在用户浏览历史中向前和向后跳转,同时——从 HTML5 开始——提供了对 history 栈中内容的操作。

二,页面跳面

前进一页:window.history.forward();
后退一页:window.history.back();
后退两页:window.history.go(-2);

三,查看历史堆栈中页面的数量

也就是一直点浏览器的前进和回退,能出现的页面总数量。

window.history.length;

四,浏览器返回不触发页面刷新现象

在IOS微信内置浏览器中返回上一页时,上一个页面不会被刷新。
而通常在浏览器缓存机制中,在返回上一页的操作中, html/css/js/接口 等动静态资源不会重新请求,但是js会重新加载。但在IOS微信页面中js也会保存上一页面最后执行的状态,不会重新执行js。
使用这种模式的缓存机制可以加快渲染速度,但是部分数据需要经常展示和编辑的情况下会导致不同步。比如‘详情页’跳转到‘编辑页’,编辑完后再返回到‘详情页’,如果‘详情页’数据展示未进行同步修改那肯定是不能接受的。
在webview和5+的混合app模式中,也会遇到这种返回上一个页面不刷新的问题。
我遇到是A项目的a页面跳转到B项目的b页面,修改了值比如说支付金额后,点击返回按钮,返回A项目的a页面,不会触发a页面的刷新,导致金额没有更新。

五,浏览器返回不触发页面刷新原因

浏览器前进/后退缓存(Backward/Forward Cache, BF Cache),当然也有人叫 disk Cache。
BF Cache 是一种浏览器优化, HTML 标准并未指定其如何进行缓存,因此缓存行为是各浏览器各自实现,所以不尽相同。
由于不是 HTTP 缓存,所以通过头文件缓存设置 no-cache 是无效的。当然也不能以 HTTP 缓存机制来理解 BF Cache。
于是,我们只要知道当前页面是ios环境下,且是返回出现的,并且从缓存中取得,那么就可以给它强制刷新下。

六,解决方法

使用ageshow,这个事件在页面显示时触发,无论页面是否来自bfcache。在重新加载页面中,pageshow会在load事件触发后触发;而对于bfcache中的页面,pageshow会在页面状态完全恢复的那一刻触发。另外要注意的是,虽然这个事件的目标是document,但必须将其事件处理程序添加到window。
值得注意的是,现在我们前端页面用的都是单页面开发,所以在自己的项目中路由跳转并不会有这个问题。因为我们是用vue-router来模拟实现的路由跳转罢了,并不是真正的window变更,所以不会触发pageShow事件。(回想一下,我们的页面其实是共用一个index.html的。页面的代码是通过标签挂载到页面上的,我们单页面项目的页面跳转,实际上只是同一个页面在不断切换其中的组件罢了)。
要触发pageShow,需要跳到另一个window然后返回,比如说百度页面。

const equipmentType = navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
  ? 'ios'
  : navigator.userAgent.indexOf('Android') > -1 ||
    navigator.userAgent.indexOf('Adr') > -1
  ? 'android'
  : 'others';
window.addEventListener('pageshow', e => {
    
    
  // persisted: 判断是否存在 BF Cache
  // performance.navigation.type: 页面通过历史记录和前进后退访问时,type值为2
  if (
    equipmentType == 'ios' &&
    router.options.history.location == '/home' &&
    (e.persisted ||
      (window.performance && window.performance.navigation.type == 2))
  ) {
    
    
    location.reload();
  }
});

除了通常的属性之外,pageshow事件的event对象还包含一个名为persisted的布尔值属性。如果页面中保存在了bfcache中,则这个属性的值为true;但是仅仅这个属性还不够,所以加了window.performance.navigation.type=2的时候就说明是返回产生的页面。

猜你喜欢

转载自blog.csdn.net/weixin_42349568/article/details/129255270