discarded 状态无法被监听,只能通过 pageshow.persisted === false、document.wasDiscarded === true 等痕迹反向推断,并在重建时结合 localStorage 时间戳等交叉验证;真正可保存现场的时机只有 freeze 和 pagehide(persisted === true)。

discarded 状态本身无法被监听或捕获,你写再多 addEventListener('discarded', ...) 都不会执行——浏览器在进入该状态时已彻底终止 JS 执行环境。所谓“利用 discarded 状态恢复现场”,实际是通过它留下的可观察痕迹反向推断,并在重建加载时做针对性还原。
pageshow 事件中 persisted === false 是 discard 的关键信号
当用户重新打开一个曾被 discarded 的 Tab,页面会像全新加载一样走完整导航流程,此时 pageshow 事件触发,且 event.persisted 为 false。这不是 bug,而是唯一可用的线索。
- 注意:这和 Frozen 后 resume 的
persisted === true完全相反,别混淆 -
pageshow在普通刷新、前进/后退、Discard 重建时都可能触发,必须靠persisted值区分 - 仅凭
persisted === false不能 100% 断定是 discard(也可能是用户手动刷新),需交叉验证
如何交叉验证是否真被 discarded
单靠 pageshow.persisted === false 不够可靠,要结合其他可读取的上下文:
- 检查
document.wasDiscarded:页面从 discard 恢复后首次 JS 执行时为true,之后刷新即变false;它是只读且瞬态的,必须在入口脚本最开头读取 - 读取
localStorage中保存的时间戳:比如上次保存时写入lastSaveTime,若距当前Date.now()差值 > 5 分钟,大概率已被 discard(Frozen 通常撑不过 2–3 分钟) - 看
performance.getEntriesByType('navigation')[0]?.type:值为'navigate'或'reload'均可能对应 discard 重建,但无法单独确认 - 主动埋点:在
pagehide或freeze中写入localStorage.setItem('_reloaded_hint', '1'),恢复时检测该 key 是否存在且未过期
真正能保存现场的只有 freeze 和 pagehide(persisted === true)
想保住状态,不能等 discard——它不可逆。必须在冻结前完成持久化,两个安全时机:
-
freeze事件:JS 尚未挂起,可安全调用localStorage.setItem()或sessionStorage.setItem();但注意该事件监听器最多运行 500ms,且不能发新网络请求 -
pagehide且event.persisted === true:说明浏览器打算缓存或冻结页面,此时也应保存;这是对不支持freeze的旧版 Safari 的兜底 - 避免重复保存:用
performance.now()记录时间戳,两次保存间隔小于 200ms 则跳过 - 别用
beforeunload:它在 discard 场景下根本不会触发
还原逻辑必须区分冷启动与热恢复
用户回到页面时,你要立刻判断这次加载属于哪一类:
- 冷启动(discard 后重建):
pageshow.persisted === false+document.wasDiscarded === true+!document.hasFocus()或 DOM 状态为空 → 从localStorage或服务端拉取最近快照,再手动 restore 表单、滚动位置、tab 选中等 - 热恢复(bfcache / frozen resume):
pageshow.persisted === true→ 可直接读取缓存状态并同步 UI,无需重新拉数据 - 还原后立即清除旧快照:避免下次冷启动又误用过期数据,例如
localStorage.removeItem('uiState') - 不要在
pageshow回调里直接操作 DOM 节点(如element.focus()),先确保节点已挂载,可用requestIdleCallback或简单延时
discarded 没有事件、没有回调、没有钩子——它的存在感只体现在页面重建后的那一瞬间。所有“恢复”动作,本质都是在冻结前就埋好伏笔,在重建后快速识别并兑现。最容易被忽略的是:你永远不知道用户切走后,页面是被 freeze、terminated 还是 discarded,所以保存逻辑必须轻量、幂等、可降级,且测试必须覆盖真机锁屏、后台切换、内存压力等真实路径。

















