一、為什么需要判斷用戶離開頁面?
在現(xiàn)代 Web 應(yīng)用中,用戶離開頁面的行為觸發(fā)的場景包括:
- 切換瀏覽器標(biāo)簽頁 / 最小化窗口(頁面不可見)
- 關(guān)閉標(biāo)簽頁 / 瀏覽器
- 導(dǎo)航到新 URL
- 移動(dòng)端切換 App 或返回主屏幕
這類行為的監(jiān)測直接關(guān)聯(lián)用戶體驗(yàn)優(yōu)化、數(shù)據(jù)埋點(diǎn)、資源釋放等核心需求,例如:
- 暫停視頻播放 / 動(dòng)畫以節(jié)省資源
- 上報(bào)用戶行為數(shù)據(jù)
- 提示未保存數(shù)據(jù)的警告
二、核心檢測方案與技術(shù)實(shí)現(xiàn)
方法一:Page Visibility API —— 現(xiàn)代瀏覽器的可見性監(jiān)測標(biāo)準(zhǔn)
核心原理:通過監(jiān)聽頁面可見性變化,判斷用戶是否切換標(biāo)簽頁或最小化窗口。
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
console.log('用戶離開當(dāng)前頁面(標(biāo)簽頁切換/窗口最小化)');
pauseVideo();
stopPolling();
} else {
console.log('用戶返回當(dāng)前頁面');
resumeVideo();
startPolling();
}
});
適用場景:
優(yōu)缺點(diǎn)對比:

方法二:beforeunload 與 unload 事件 —— 傳統(tǒng)的頁面卸載監(jiān)聽
1. beforeunload 事件(離開前確認(rèn))
window.addEventListener('beforeunload', (event) => {
// 防止未保存數(shù)據(jù)丟失(瀏覽器會(huì)顯示默認(rèn)確認(rèn)框)
event.preventDefault()
event.returnValue = '確定要離開嗎?未保存的數(shù)據(jù)將丟失'
// 注意:現(xiàn)代瀏覽器會(huì)忽略returnValue,顯示標(biāo)準(zhǔn)化提示
})
2. unload 事件(頁面開始卸載時(shí)觸發(fā))
window.addEventListener('unload', () => {
console.log('用戶正在關(guān)閉或離開頁面');
});
適用場景:
提示用戶保存未完成的表單數(shù)據(jù)
簡單的資源清理(同步操作)
優(yōu)缺點(diǎn)對比:

方法三:navigator.sendBeacon () —— 可靠的數(shù)據(jù)上報(bào)方案
核心優(yōu)勢:解決 unload 事件中網(wǎng)絡(luò)請求不可靠的問題,確保數(shù)據(jù)發(fā)送完成。
window.addEventListener('pagehide', () => {
const analyticsData = {
pageDuration: calculateStayTime(),
lastAction: 'leave-page'
};
navigator.sendBeacon('/analytics', JSON.stringify(analyticsData));
});
適用場景:
關(guān)鍵特性:
- 瀏覽器保證數(shù)據(jù)發(fā)送完成,即使頁面已關(guān)閉
- 支持 POST 請求,數(shù)據(jù)大小限制通常為 64KB
方法四:pagehide 與 pageshow 事件 —— 應(yīng)對往返緩存(bfcache)
核心原理:監(jiān)聽頁面進(jìn)入 / 退出緩存狀態(tài),解決 unload 在 bfcache 下不觸發(fā)的問題。
window.addEventListener('pagehide', (event) => {
if (event.persisted) {
console.log('頁面進(jìn)入往返緩存(點(diǎn)擊后退/前進(jìn)時(shí)緩存)');
} else {
console.log('頁面正常卸載');
}
navigator.sendBeacon('/log', getExitData());
});
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
console.log('頁面從緩存中恢復(fù)');
resetPageState();
}
});
適用場景:
- 移動(dòng)端瀏覽器的頁面緩存處理
- 確保數(shù)據(jù)上報(bào)在所有卸載場景下觸發(fā)
三、最佳實(shí)踐與組合方案
- 可見性監(jiān)測:優(yōu)先使用
Page Visibility API
處理標(biāo)簽頁切換場景。 - 數(shù)據(jù)上報(bào):結(jié)合
pagehide
與 navigator.sendBeacon()
,確保數(shù)據(jù)可靠發(fā)送。 - 防數(shù)據(jù)丟失:謹(jǐn)慎使用
beforeunload
,僅在必要時(shí)提示用戶保存數(shù)據(jù)。 - 資源管理:在
visibilitychange
中暫停非必要任務(wù),在 pageshow
中恢復(fù)。
四、兼容性與性能優(yōu)化
- 瀏覽器兼容:
Page Visibility API
在 IE10+、Chrome、Firefox 等現(xiàn)代瀏覽器中全支持;sendBeacon()
在 IE11 + 及主流瀏覽器中可用。 - 性能建議:
避免在 unload
中執(zhí)行復(fù)雜邏輯或異步請求
visibilitychange
事件處理函數(shù)需輕量化,減少 DOM 操作
數(shù)據(jù)上報(bào)使用 sendBeacon()
而非傳統(tǒng) XHR/fetch
通過組合運(yùn)用上述 API,前端可以精準(zhǔn)捕獲用戶離開頁面的各類場景,在不影響性能的前提下實(shí)現(xiàn)智能化的用戶行為響應(yīng),為應(yīng)用體驗(yàn)優(yōu)化和數(shù)據(jù)采集提供可靠支撐。
?轉(zhuǎn)自https://juejin.cn/post/7520063683179970623
該文章在 2025/9/6 17:20:19 編輯過