onpageshow 事件必须绑定到 window 对象而非 body 标签,因它是全局页面生命周期事件,触发早于 dom 完全解析,且不冒泡;内联写法无法访问 event.persisted,现代浏览器中基本失效;唯一可靠写法是 window.addeventlistener("pageshow", ...)。

onpageshow 不该写在 标签上——它虽然被文档标记为支持 ,但实际绑定到 window 才可靠,且现代浏览器中直接写 HTML 属性(如 )基本失效或不可预测。
为什么不能用
HTML 属性式绑定依赖元素存在且能响应事件,但 pageshow 是全局页面生命周期事件,触发时机早于 DOM 完全解析完成; 可能尚未挂载,或即使挂载了,事件也不会冒泡(技术细节明确标注“不支持冒泡”),导致回调不执行。实测 Chrome 11+、Firefox 5+、Safari 均无法稳定触发该写法。
更关键的是:event.persisted 必须通过事件对象获取,而内联写法无法访问 event 参数,形同虚设。
window.addEventListener("pageshow", ...) 是唯一推荐写法
必须用 addEventListener 绑定到 window,并检查 event.persisted 值来区分加载来源:
-
event.persisted === false→ 页面首次加载或硬刷新,可执行初始化逻辑(如拉取最新数据、重置表单) -
event.persisted === true→ 页面从 bfcache 恢复(典型场景:用户点击后退/前进按钮),此时 DOM 和 JS 状态是冻结快照,需手动刷新时间、重置过期验证码、重新 fetch 接口等
示例:
window.addEventListener("pageshow", function(event) {
if (event.persisted) {
// 后退/前进恢复时执行
document.getElementById("timestamp").textContent = new Date().toISOString();
refreshCaptcha(); // 重绘图形验证码
}
});
注意:不要在 pageshow 中无条件调用 location.reload()——这会破坏 bfcache 的性能优势,且可能造成循环刷新。
IE8– 不支持 addEventListener?那就别管它
知识库提到 IE8 及更早版本不支持 addEventListener,但当前时间是 2026 年,所有主流项目早已放弃对 IE 的兼容。强行降级用 window.onpageshow = function(){...} 写法虽能运行,但无法移除监听、不支持多监听器、且在某些 Safari 版本中行为异常。坚持用 addEventListener 即可。
如果真有遗留系统要求兼容旧 IE,应整体重构缓存策略,而非在 pageshow 上打补丁。
容易被忽略的点:pageshow 触发时机比 DOMContentLoaded 还早
它甚至可能在 元素创建前就触发。所以任何依赖 DOM 节点的操作(比如 document.getElementById)必须加防护:
错误写法:document.getElementById("demo").innerText = "hello";(可能报 null)
正确写法:用 event.target 或延迟到 DOMContentLoaded 后执行,或加存在性判断:
window.addEventListener("pageshow", function(event) {
if (event.persisted) {
const el = document.getElementById("demo");
if (el) el.innerText = new Date().toISOString();
}
});
bfcache 恢复时 DOM 是完整可用的,但脚本执行顺序不受控——这点和很多人直觉相反,也是最常踩的坑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











