一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何利用 Page Lifecycle API 的 discarded 状态还原被浏览器主动回收的页面现场

时间:2026-07-18 10:55:49 编辑:袖梨 来源:一聚教程网

discarded 状态无法被 JavaScript 捕获,唯一线索是 pageshow 事件中 persisted === false 且为全新加载;可靠保存时机仅 freeze 事件和 pagehide 且 persisted === true;还原需区分冷启动与热恢复,并清除旧快照。

discarded 状态无法被 JavaScript 捕获或响应

页面进入 discarded 阶段时,浏览器已彻底终止 JS 执行环境,所有监听器、定时器、fetch 请求、甚至 beforeunload 都不会触发。这不是一个可监听的生命周期事件,而是一个「事后状态」——你只能在用户**重新打开该 Tab** 时,通过判断加载上下文来推测它曾被丢弃。

pageshow 事件里的 persisted 属性是唯一线索

当用户从任务管理器或后台切回一个被丢弃后重建的 Tab,浏览器会重新加载整个页面(即发起新 navigation),此时 pageshow 事件会触发,且 event.persisted === false —— 注意:这和 Frozen 后恢复的 persisted === true 正好相反。

关键点在于:persisted === false 不代表“没被丢弃”,而是代表“这次不是从缓存恢复”,即一次全新加载。你需要结合其他信号交叉判断:

  • 检查 URL 参数是否含 ?_reloaded=1 或类似标记(需你主动在上一次页面卸载前写入 localStorage)
  • 读取 localStorage 中保存的最后状态时间戳,若距当前时间 > 5 分钟,大概率已被 discard(Frozen 通常撑不过 2–3 分钟)
  • 检测 performance.navigation.type 已废弃,改用 performance.getEntriesByType('navigation')[0]?.type,值为 'reload''navigate' 均可能对应 discard 后重建

真正能保存现场的只有 freeze + pagehide(persisted=true)

想保住用户现场,不能等 discarded——它不可逆。必须在进入 frozen 前完成持久化。可靠时机只有两个:

  • freeze 事件:页面即将冻结,JS 还能执行,是最后安全的保存窗口
  • pagehide 事件且 event.persisted === true:说明页面将被放入 bfcache,后续可能直接 resume,此时也应保存关键状态

这两个事件中,你可以安全调用 localStorage.setItem()indexedDB 写入、或发送带 keepalive: truenavigator.sendBeacon() 上报快照。但注意:sendBeacon()freeze 中不一定发出,优先用存储类方案。

还原逻辑必须区分「冷启动」和「热恢复」

用户回到页面时,你要立刻判断这次加载是:

  • 冷启动(discard 后重建):无有效缓存、pageshow.persisted === falsedocument.hasFocus() === true 且无残留 DOM 状态 → 从 localStorage 或服务端拉取最近快照,再手动 restore 表单、滚动位置、选中项等
  • 热恢复(bfcache resume):pageshow.persisted === true → 不要重置 DOM,只需校验并补全异步数据(如 token 过期、列表陈旧)

最容易被忽略的是:冷启动还原后,必须清除旧的 localStorage 快照,否则下次再进还会误还原;同时滚动位置恢复要用 history.scrollRestoration = 'manual' 配合 scrollTo(),避免浏览器默认行为覆盖你的逻辑。

热门栏目