移动端H5页面返回并且刷新页面(BFcache)

探讨如何通过监听pageshow事件并利用persisted属性,禁用bfcache以实现浏览器返回时页面资源的重新加载,确保内容更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中的需求:点击浏览器中的返回按钮,要让页面重新加载资源。因为这部分的资源每次去加载的内容都不一样,如果返回的时候,还是看到原先的内容,那做这个内容块的意义就很小了;而如果用户看完了这部分内容,再返回来的时候,这个地方换成了新的内容,这样就能体现这部分的价值了。

而对于浏览器来说,大部分浏览器的返回是直接使用缓存的,不会执行任何的javascript代码。原因:部分浏览器在后退时不会触发onload事件,這是HTML5世代浏览器新增的特性之一——Back-Forward Cache(简称bfcache)

什么是bfcache?

bfcache,即back-forward cache,可称为“往返缓存”,可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。这个缓存不仅保存页面数据,还保存了DOM和JS的状态,实际上是将整个页面都保存在内存里。如果页面位于bfcache中,那么再次打开该页面就不会触发onload事件

pageshow事件

这个事件在用户浏览网页时触发,pageshow 事件类似于 onload 事件,onload 事件在页面第一次加载时触发, pageshow 事件在每次加载页面时触发,即 onload 事件在页面从浏览器缓存中读取时不触发。

pagehide事件

该事件会在用户离开网页时触发。离开网页有多种方式。如点击一个链接,刷新页面,提交表单,关闭浏览器等。pagehide 事件有时可以替代 unload事件,但 unload 事件触发后无法缓存页面。

persisted属性

pageshow事件和pagehide事件的event对象还包含一个名为persisted的布尔值属性。

  对于pageshow事件,如果页面是从bfcache中加载的,则这个属性的值为true;否则,这个属性的值为false。
  对于pagehide事件,如果页面在卸载之后被保存在bfcache中,则这个属性的值为true;否则,这个属性的值为false。

不同的浏览器在对当前窗口‘打开’历史记录中的前一个页面的表现上并不统一,这和浏览器的实现以及页面本身的设置有关系。

解决方案:

javascript监听pageshow事件阻止页面进入bfcache

 window.addEventListener('pageshow', function (e) {
     if (e.persisted) {
         window.location.reload()
     }
})

在uc和微信中测试通过,但是在某些安卓手机自带的浏览器中无效。

javascript监听pagehide事件阻止页面进入bfcache

window.addEventListener('pagehide', function (e) {
    var dom = document.body;
    dom.children.remove();
    setTimeout(function () {
        dom.appendChild("<script type='text/javascript'>window.location.reload();<\/script>");
    });
});

设置meta标签,清除页面缓存

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如下
Public指示响应可被任何缓存区缓存
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
注:有些情况下设置清除缓存也没有起到作用,我自己做的这个h5页面就没有起到效果。具体情况还是要具体分析。

我遇到的情况:

<div class="content">
     <iframe id="iframe" src="https://cpu.baidu.com/xx/xx/xxx" frameborder="no" scrolling="no"></iframe>
</div>

这个iframe中的地址每次刷新页面都会有不同的内容推送给用户。进入iframe中的内容之后,按返回按钮返回来想进行页面自动刷新,为的就是让用户看到新的内容。

做法:

使用pageshow进行整个页面刷新

 window.addEventListener('pageshow', function (e) {
     if (e.persisted) {
         window.location.reload()
     }
 })

这样可以实现。

后面又觉得不妥,没有因为这个小部分而进行整个页面刷新,想到了另一种思路:因为这个iframe中的内容是动态的,可以对其进行定时器设置,如下:

 let iframe = document.getElementById('iframe')
 setInterval(() => {
     iframe.setAttribute("src", "https://cpu.baidu.com/xx/xx/xx");
 },15000)

这样也可以实现自己的功能。

最后可以结合一下:

let iframe = document.getElementById('iframe')
window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
        iframe.setAttribute("src", "https://cpu.baidu.com/xx/xx/xx");
    }
})

这样做也有好处,可以避免使用定时器,对网页的性能也是比较好。但是这个方法在返回的时候,可以看到iframe里面内容的重新加载,会有一个时间间隙。

 

转载于:https://www.cnblogs.com/zengfp/p/9910473.html

<think>我们正在解决移动端页面跳转后返回上一页并刷新页面的需求。根据引用内容,有几种常见方法: 1. 使用`onActivityResult`方法(Android原生开发)[^1]:适用于Android原生应用,在Activity中重写此方法,当从下一个页面返回时自动调用,可在此触发刷新操作。 2. 使用`sessionStorage`配合`pageshow`事件(Web前端)[^2][^5]:这是Web移动端的解决方案。具体步骤: - 在目标页面(如b页面)操作完成后,设置一个标志到`sessionStorage`,然后返回上一页(a页面)。 - 在a页面监听`pageshow`事件,检查该标志,如果存在则刷新页面并清除标志。 3. 使用`document.referrer`(Web前端)[^4]:通过检查`document.referrer`来判断来源页面,然后跳转回去并刷新。但这种方法只能返回上一页并刷新,不能处理多层返回。 根据用户需求,我们是在移动端(假设是Web页面)实现返回刷新。因此,我们重点使用第二种方法。 具体实现步骤: a.html(原页面): ```html <!DOCTYPE html> <html> <head> <title>A页面</title> </head> <body> <h1>A页面</h1> <a href="b.html">跳转到B页面</a> <script> // 监听pageshow事件 window.addEventListener('pageshow', function(event) { // 检查sessionStorage中是否有需要刷新的标志 if (sessionStorage.getItem('need-refresh') === 'true') { // 刷新页面 location.reload(); // 清除标志 sessionStorage.removeItem('need-refresh'); } }); </script> </body> </html> ``` b.html(目标页面): ```html <!DOCTYPE html> <html> <head> <title>B页面</title> </head> <body> <h1>B页面</h1> <button onclick="goBack()">返回刷新A页面</button> <script> function goBack() { // 设置需要刷新的标志 sessionStorage.setItem('need-refresh', 'true'); // 返回上一页 window.history.go(-1); } </script> </body> </html> ``` 说明: - 当用户从a页面跳转到b页面后,在b页面点击按钮返回时,会设置一个`sessionStorage`标志。 - 当返回到a页面时,a页面的`pageshow`事件被触发,检查到标志则刷新页面。 注意事项: 1. `pageshow`事件在页面显示时都会触发,包括首次加载和从缓存中恢复(如返回)。但注意,如果页面是从前进/后退缓存(bfcache)中恢复,则不会重新加载页面,所以需要这个事件来检测。 2. 使用`sessionStorage`是因为它的生命周期是页面会话期间,且在同一标签页内共享,适合这种场景。 另外,如果用户使用的是单页面应用(SPA),则不需要刷新整个页面,而是通过状态管理或路由钩子来更新数据[^3]。但用户的问题要求刷新页面,所以上述方法适用于多页面应用。 如果用户想要返回上一页以上(比如上两页)并刷新,则这种方法不适用,需要更复杂的路由管理。但根据引用[^4],使用`document.referrer`只能返回上一页。 因此,对于返回上一页并刷新的需求,推荐使用`sessionStorage`+`pageshow`事件的方法。 相关问题: 1. 如何实现移动端返回上一页但不刷新? 2. 在单页面应用中如何实现返回时更新数据? 3. 如何实现返回上两页并刷新?</think>### 移动端页面跳转后返回上一页并刷新页面解决方案 在移动端开发中,实现返回上一页并刷新页面主要有以下三种方法: #### 方法一:使用 sessionStorage + pageshow 事件(推荐) 这是最常用的跨浏览器解决方案,通过本地存储传递刷新标志: ```html <!-- a.html(原页面) --> <script> // 监听页面显示事件 window.addEventListener("pageshow", function() { // 检查是否需要刷新 if(sessionStorage.getItem("need-refresh") === "true") { location.reload(); // 刷新页面 sessionStorage.removeItem("need-refresh"); // 清除标记 } }); </script> <!-- b.html(跳转页面) --> <script> function returnToPageA() { // 设置刷新标记 sessionStorage.setItem("need-refresh", "true"); // 返回上一页 window.history.go(-1); } </script> ``` **原理**: 在b页面设置刷新标记`sessionStorage.setItem("need-refresh", true)`,返回a页面时通过`pageshow`事件检测该标记并执行刷新[^2][^5]。 #### 方法二:Android原生方案(适用于App) 在Activity中重写`onActivityResult`方法: ```java // 在a页面Activity中 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 刷新页面逻辑 refreshContent(); // 自定义刷新方法 } ``` **说明**: 当从b页面返回a页面时,系统会自动调用此方法触发刷新[^1]。 #### 方法三:document.referrer(简单场景) ```javascript function returnToPrevious() { if(document.referrer && document.referrer !== location.href) { location.href = document.referrer + "?refresh=" + Date.now(); } else { history.back(); } } ``` **注意**: 此方法通过URL参数强制刷新,但可能遇到跨域限制和参数污染问题[^4]。 ### 最佳实践建议 1. **Web应用**:优先采用`sessionStorage+pageshow`方案,兼容性好且无副作用 2. **混合开发**:在WebView中可通过JS Bridge调用原生刷新方法 3. **单页面应用(SPA)**:建议使用路由状态管理(如Vue Router的导航守卫)实现无刷新更新[^3] 4. **防抖动处理**:在刷新逻辑中添加防抖机制,避免频繁刷新 > ⚠️ 注意事项: > - `pageshow`事件在页面从缓存恢复时也会触发 > - 单页面应用应避免整页刷新,改用AJAX局部更新[^3] > - iOS Safari中需注意页面缓存策略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值