beforeunload 事件用于页面卸载前同步保存关键状态并提示用户,但仅支持返回字符串触发默认提示框,禁止异步操作;推荐结合 localstorage 持续保存与 beforeunload 兜底提示。

在页面即将卸载(如关闭标签页、刷新、导航离开)前,可以使用 beforeunload 事件触发轻量级状态保存,但需注意它的限制:浏览器只允许同步操作,且不能执行异步请求(如 fetch 或 XMLHttpRequest),也不能显示自定义弹窗——仅支持返回字符串以触发默认提示框。
beforeunload 的基本用法和触发条件
该事件在用户尝试离开当前页面时同步触发,适用于保存少量关键状态(如表单草稿、滚动位置、选中项等)。它必须在事件处理函数中返回一个非空字符串(现代浏览器会忽略该字符串内容,但返回动作本身是必需的),否则事件无效。
- 监听方式:
window.addEventListener('beforeunload', handler) - 必须返回字符串(例如
return '数据未保存,确定要离开?'),否则 Chrome/Firefox 等将不显示提示 - 仅适用于用户主动触发的卸载行为(刷新、关闭、后退/前进、输入新 URL),不适用于
location.replace()或history.pushState()后的跳转
推荐做法:用 localStorage 提前持久化 + beforeunload 做兜底
beforeunload 不适合做主保存逻辑,因为它是最后时刻、不可靠且无法异步。正确策略是「持续保存 + 卸载确认」:
- 在用户输入、切换选项、滚动等操作中,实时或节流写入
localStorage(如localStorage.setItem('draft', JSON.stringify(data))) - 在
beforeunload中仅检查是否有未提交的变更,若有则返回提示字符串,提醒用户可能丢失数据 - 页面加载时优先从
localStorage恢复状态(并可选择性清除,避免残留)
代码示例:表单草稿自动保存与卸载提示
(注意:以下为可直接运行的简洁示例)
// 持续保存到 localStorage(例如监听 input)
document.getElementById('myForm').addEventListener('input', function(e) {
const draft = { text: e.target.value, timestamp: Date.now() };
localStorage.setItem('formDraft', JSON.stringify(draft));
});
// beforeunload 提示(仅当有未保存变更时)
let hasUnsavedChanges = false;
document.getElementById('myForm').addEventListener('input', () => hasUnsavedChanges = true);
window.addEventListener('beforeunload', function(e) {
if (hasUnsavedChanges) {
e.preventDefault();
e.returnValue = ''; // 必须设置(兼容旧版),现代浏览器忽略内容
return '';
}
});
// 页面加载时恢复(可选)
if (localStorage.getItem('formDraft')) {
const draft = JSON.parse(localStorage.getItem('formDraft'));
document.getElementById('myForm').value = draft.text;
}
重要限制与替代方案
beforeunload 在现代 Web 应用中越来越受限:
- 移动端 Safari 和部分 Android 浏览器完全不支持该事件提示
- PWA 或单页应用(SPA)中,路由跳转不触发
beforeunload,应改用路由守卫(如 React Router 的useBlocker) - 若需可靠上传(如日志、分析数据),应在卸载前用
navigator.sendBeacon()发送小量数据(支持异步、不阻塞卸载)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











