兩種主要事件
| 事件 | 觸發時機 | 可取消導航 | 典型用途 | 瀏覽器限制 |
beforeunload | 文件即將卸載(關閉分頁、重新整理、跳轉) | 是:回傳字串/真值觸發確認對話框 | 未儲存資料提醒 | 現代瀏覽器忽略自訂訊息,只顯示預設文字;需使用者先互動頁面 |
unload | 文件已卸載 | 否 | 發送統計、清理資源 | 不可執行非同步操作 (fetch/XHR 需 navigator.sendBeacon) |
標準用法
// 1. beforeunload:提醒未儲存
window.addEventListener('beforeunload', (e) => {
if (hasUnsavedChanges) {
e.preventDefault(); // 標準取消方式
e.returnValue = ''; // Chrome/Edge/Firefox 需要
// return ''; // 老舊寫法仍相容
}
});
// 2. unload:發送分析資料 (不可阻塞)
window.addEventListener('unload', () => {
navigator.sendBeacon('/analytics/leave', JSON.stringify({page: location.pathname}));
});
// 3. jQuery 寫法 (不建議新專案用)
$(window).on('beforeunload', () => hasUnsavedChanges ? '您有未儲存變更' : null);
關鍵限制與最佳實踐
- 使用者互動門檻:瀏覽器要求頁面曾被使用者互動(點擊、鍵盤、觸控)才會顯示
beforeunload 確認框,否則靜默忽略。
- 自訂訊息已失效:Chrome 51+、Firefox 44+、Safari 11+ 均忽略回傳字串,統一顯示瀏覽器預設訊息(如「您輸入的內容可能不會被儲存」)。
- 非同步操作不可靠:
unload 中 fetch(..., {keepalive:true}) 或 navigator.sendBeacon 才有機會送達;beforeunload 內不可做非同步。
- 行動裝置行為不同:iOS Safari 在切換 App/鎖屏時不一定觸發
beforeunload;pagehide (配合 pageshow) 較可靠。
- SPA (Vue/React) 路由切換不觸發:需用框架提供的導航守衛(
beforeRouteLeave、useEffect cleanup)。
完整頁面生命週期事件順序
// 載入
DOMContentLoaded → load
// 可見性變更
visibilitychange (document.hidden)
// 離開流程
pagehide (persisted=true 表示可能從 bfcache 恢復)
beforeunload (可取消)
unload (不可取消, 同步執行)
現代替代:Page Lifecycle API
document.addEventListener('freeze', () => { /* 釋放資源 */ });
document.addEventListener('resume', () => { /* 重建資源 */ });