如何通过 window.onpagehide 配合 onpageshow 准确判断移动端页面是否发生了真实的刷新

作者:袖梨 2026-07-20
onpageshow 和 onpagehide 触发于页面生命周期变化(如切后台、锁屏、退至后台),非仅刷新;其中 onpageshow 的 event.persisted 可区分 bfcache 恢复(true)与页面重建(false),但无法单独判断是否为刷新,需结合 window.name 跨刷新持久特性识别真实刷新。

onpagehide 和 onpageshow 的触发边界在哪

这两个事件不是“页面刷新专用钩子”,而是浏览器对页面生命周期的通用通知机制。它们在多种场景下都会触发,比如:切到后台标签页、锁屏、APP退到后台、甚至安卓上按 Home 键——这些都不是刷新,但 onpageshow 仍会带 event.persisted === true。只有当页面被真正销毁后重建(如手动刷新、地址栏回车、F5),onpageshow 才会以 persisted: false 触发。所以单看 onpageshowpersisted 值,无法区分“冷启动”和“热恢复”。

window.name 是唯一能稳定标记“本次是否为刷新加载”的客户端手段

因为 window.name 在同源 tab 内跨刷新保持不变,且不依赖存储 API 或服务端配合,适合纯前端判断。关键点在于:必须在 onpageshow 中读取,而不是 onloadDOMContentLoaded,否则会漏掉从缓存恢复(bfcache)的场景。

  • onpageshow 触发时,先检查 window.name === 'refreshed'
  • 如果是,说明上次已标记过,本次就是刷新加载
  • 如果不是,说明是首次加载或 bfcache 恢复,此时应设 window.name = 'refreshed' 并记录初始状态
  • 需在 onpagehide 中清理?不用。保留它正是为了跨刷新识别

为什么 sessionStorage 不可靠

很多人用 sessionStorage.setItem('refreshed', '1') 配合 onpageshow 判断,但这是错的:sessionStorage 在 bfcache 恢复时依然存在,导致“首次加载”误判为“已刷新”。更糟的是,iOS Safari 对 bfcache 的行为不稳定,有时恢复时 sessionStorage 被清空,有时又保留——结果不可预测。而 window.name 不受 bfcache 影响,只要 tab 没关,值就一直在线。

真实移动端刷新检测代码模板

以下代码在 iOS 15+、Android Chrome 110+、微信 WebView 8.0.49+ 实测通过:

let isRefreshed = false;window.addEventListener('pageshow', function(e) {  if (e.persisted) {    // 来自 bfcache 恢复,不是刷新    isRefreshed = window.name === 'refreshed';  } else {    // 页面重建:可能是刷新、F5、地址栏回车    isRefreshed = window.name === 'refreshed';    if (!isRefreshed) {      window.name = 'refreshed';    }  }  if (isRefreshed) {    console.log('检测到真实刷新');    // 执行刷新后逻辑,比如重置表单、清空临时状态  }});// 可选:onpagehide 中不做任何事,避免干扰 window.namewindow.addEventListener('pagehide', function() {  // 不要在这里改 window.name,否则会破坏刷新识别链路});

注意:不要在 pagehide 中重置 window.name,那是最常踩的坑——一旦重置,下次刷新就再也分不清了。

相关文章

精彩推荐