在Web应用中,防止用户意外关闭页面导致数据丢失是一个常见的需求。以下是几种有效的JavaScript实现方案:
beforeunload
事件这是最常用的方法,会在用户尝试离开页面时触发确认对话框。
window.addEventListener('beforeunload', function(e) {
// 检查是否有未保存的数据
if (hasUnsavedChanges()) {
// 标准方式(现代浏览器)
e.preventDefault();
// 为了兼容旧浏览器,需要设置returnValue
e.returnValue = '';
// 返回的字符串在大多数现代浏览器中不会显示
return '';
}
// 如果没有未保存的数据,不执行任何操作
});
function hasUnsavedChanges() {
// 实现你的逻辑检查是否有未保存的更改
// 返回true表示有未保存数据
}
注意:现代浏览器会显示自己的默认消息,你不能自定义消息内容。
更友好的方式是定期自动保存数据:
// 定期自动保存(每30秒)
const AUTO_SAVE_INTERVAL = 30000;
let saveTimer;
function startAutoSave() {
saveTimer = setInterval(() => {
if (hasUnsavedChanges()) {
saveData();
}
}, AUTO_SAVE_INTERVAL);
}
// 页面加载时启动自动保存
window.addEventListener('load', startAutoSave);
// 页面卸载时执行最后一次保存
window.addEventListener('beforeunload', () => {
if (hasUnsavedChanges()) {
// 同步保存,确保数据不会丢失
saveDataSync();
}
clearInterval(saveTimer);
});
// 保存数据到localStorage
function saveToLocalStorage(data) {
localStorage.setItem('draft_data', JSON.stringify(data));
}
// 从localStorage恢复数据
function restoreFromLocalStorage() {
const data = localStorage.getItem('draft_data');
return data ? JSON.parse(data) : null;
}
// 页面加载时检查是否有暂存数据
window.addEventListener('load', () => {
const savedData = restoreFromLocalStorage();
if (savedData) {
// 询问用户是否要恢复数据
if (confirm('检测到未保存的草稿,是否恢复?')) {
loadData(savedData);
}
// 无论用户选择什么,都清除暂存数据
localStorage.removeItem('draft_data');
}
});
// 监听输入变化,定期保存
document.getElementById('input-field').addEventListener('input', () => {
saveToLocalStorage(getCurrentFormData());
});
对于更高级的应用,可以使用Service Worker来缓存未提交的数据:
// 在Service Worker中
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/save-draft')) {
event.respondWith(
caches.open('drafts').then((cache) => {
return fetch(event.request)
.then((response) => {
cache.put(event.request, response.clone());
return response;
})
.catch(() => {
return caches.match(event.request);
});
})
);
}
});
beforeunload
事件beforeunload
事件的支持可能不同对于更精细的控制,可以使用新的Page Lifecycle API:
// 监听页面冻结事件(浏览器可能为了节省资源冻结页面)
document.addEventListener('freeze', (event) => {
// 保存当前状态
saveData();
});
// 监听页面恢复事件
document.addEventListener('resume', (event) => {
// 检查是否需要恢复数据
});
选择哪种方案取决于你的具体需求和目标浏览器支持情况。