在 Web 開(kāi)發(fā)中,我們經(jīng)常需要區(qū)分用戶(hù)是否通過(guò)刷新操作重新加載了頁(yè)面。這一操作可能是由用戶(hù)手動(dòng)刷新(如按下 F5 鍵或點(diǎn)擊瀏覽器刷新按鈕)或通過(guò)瀏覽器自動(dòng)重新加載。判斷頁(yè)面是否刷新有助于開(kāi)發(fā)者優(yōu)化用戶(hù)體驗(yàn),例如在使用 vue 的時(shí)候需要進(jìn)行權(quán)限控制,就需要判斷在刷新后根據(jù)登錄者的權(quán)限去添加對(duì)應(yīng)的路由。
本文將詳細(xì)解析幾種常見(jiàn)的判斷頁(yè)面是否刷新的技術(shù)方案,并探討各自的適用場(chǎng)景、優(yōu)缺點(diǎn)以及瀏覽器的兼容性。
1. 使用 window.name
window.name
是一個(gè)持久的窗口屬性,它的值在頁(yè)面刷新、甚至通過(guò)標(biāo)簽頁(yè)導(dǎo)航到其他頁(yè)面時(shí)也會(huì)保留,因此可以利用它來(lái)判斷頁(yè)面是否是通過(guò)刷新重新加載。
代碼示例
window.onload = function() {
if (window.name === 'isRefreshed') {
console.log('頁(yè)面被刷新');
} else {
console.log('首次加載頁(yè)面');
window.name = 'isRefreshed';
}
};
工作原理
優(yōu)點(diǎn)
缺點(diǎn)
兼容性
window.name
是一個(gè)非常老的 Web API,幾乎在所有瀏覽器中都有廣泛的支持,包括:

2. 使用 sessionStorage
sessionStorage
是 Web 存儲(chǔ) API 的一部分,它為每個(gè)標(biāo)簽頁(yè)維護(hù)獨(dú)立的存儲(chǔ)空間,并且其數(shù)據(jù)在標(biāo)簽頁(yè)關(guān)閉后會(huì)被清空。我們可以利用 sessionStorage
來(lái)判斷頁(yè)面是否被刷新:
window.onload = function() {
if (sessionStorage.getItem('isRefreshed')) {
console.log('頁(yè)面被刷新');
} else {
console.log('首次加載頁(yè)面');
}
sessionStorage.setItem('isRefreshed', true);
};
工作原理
當(dāng)頁(yè)面首次加載時(shí),sessionStorage
中沒(méi)有 isRefreshed
條目,因此可以判斷這是首次加載。
通過(guò)設(shè)置 sessionStorage.setItem('isRefreshed', true);
,標(biāo)記頁(yè)面已加載。
當(dāng)頁(yè)面刷新后,sessionStorage
中的 isRefreshed
條目依然存在,因此可以檢測(cè)到頁(yè)面的刷新操作。
優(yōu)點(diǎn)
缺點(diǎn)
兼容性
sessionStorage
是廣泛支持的 API,適用于以下瀏覽器:

瀏覽器的 performance.navigation
API 提供了頁(yè)面加載的詳細(xì)信息,包括是否是通過(guò)刷新操作加載的頁(yè)面。通過(guò)檢查 performance.navigation.type
屬性可以判斷頁(yè)面的加載方式。
window.onload = function() {
if (performance.navigation.type === performance.navigation.TYPE_RELOAD) {
console.log('頁(yè)面被刷新');
} else {
console.log('首次加載頁(yè)面');
}
};
屬性解釋
優(yōu)點(diǎn)
缺點(diǎn)
兼容性
performance.navigation
API 在大多數(shù)瀏覽器中都被支持,但該 API 已逐步被棄用:

4. 使用 beforeunload
事件
beforeunload
事件在用戶(hù)離開(kāi)頁(yè)面之前觸發(fā),無(wú)論是頁(yè)面刷新、關(guān)閉還是導(dǎo)航到其他頁(yè)面。在此事件中,我們可以設(shè)置一個(gè)標(biāo)志位來(lái)判斷用戶(hù)是否通過(guò)刷新離開(kāi)當(dāng)前頁(yè)面。
window.addEventListener('beforeunload', function() {
localStorage.setItem('isRefreshed', 'true');
});
window.onload = function() {
if (localStorage.getItem('isRefreshed') === 'true') {
console.log('頁(yè)面被刷新');
localStorage.removeItem('isRefreshed'); // 刷新后清除標(biāo)志位
} else {
console.log('首次加載頁(yè)面');
}
};
工作原理
優(yōu)點(diǎn)
缺點(diǎn)
兼容性
beforeunload
事件在大多數(shù)現(xiàn)代瀏覽器中都有廣泛支持,但可能在一些移動(dòng)端瀏覽器上表現(xiàn)不一致:

performance.getEntriesByType("navigation")
是一個(gè)現(xiàn)代 Web 性能 API,用于獲取頁(yè)面導(dǎo)航的詳細(xì)信息。通過(guò)這個(gè)方法,我們可以獲取一個(gè)包含導(dǎo)航信息的對(duì)象,并通過(guò)檢查該對(duì)象的 type
屬性,判斷頁(yè)面是通過(guò)刷新加載還是其他方式進(jìn)入的。
示例代碼
window.onload = function() {
const [navigationEntry] = performance.getEntriesByType('navigation');
if (navigationEntry && navigationEntry.type === 'reload') {
console.log('頁(yè)面被刷新');
} else {
console.log('首次加載頁(yè)面');
}
};
工作原理
優(yōu)點(diǎn)
現(xiàn)代性:performance.getEntriesByType
是較新的 API,能夠在現(xiàn)代瀏覽器中準(zhǔn)確區(qū)分頁(yè)面的導(dǎo)航方式。
詳細(xì)信息:除了判斷頁(yè)面刷新,還可以獲取更多關(guān)于頁(yè)面加載性能的數(shù)據(jù),如 DNS 解析時(shí)間、請(qǐng)求時(shí)間等,有助于調(diào)優(yōu)頁(yè)面性能。
無(wú)狀態(tài)管理:無(wú)需依賴(lài) sessionStorage
、localStorage
等外部狀態(tài),避免了狀態(tài)同步問(wèn)題。
缺點(diǎn)
使用場(chǎng)景
performance.getEntriesByType
適合那些只需要快速判斷頁(yè)面是否是刷新加載的場(chǎng)景,并且同時(shí)有進(jìn)一步性能優(yōu)化需求的應(yīng)用。對(duì)于現(xiàn)代 Web 開(kāi)發(fā),這是一個(gè)較為精確且無(wú)需額外存儲(chǔ)或會(huì)話(huà)管理的解決方案。
監(jiān)控頁(yè)面加載性能示例
window.onload = function() {
const [navigationEntry] = performance.getEntriesByType('navigation');
if (navigationEntry) {
console.log(`頁(yè)面加載類(lèi)型: ${navigationEntry.type}`);
console.log(`頁(yè)面加載時(shí)間: ${navigationEntry.loadEventEnd - navigationEntry.startTime} ms`);
}
};
這種方式不僅能幫助判斷頁(yè)面加載類(lèi)型,還能幫助開(kāi)發(fā)者優(yōu)化頁(yè)面性能,提供更多性能數(shù)據(jù)來(lái)分析頁(yè)面加載瓶頸。
兼容性
performance.getEntriesByType
是較新的 API,在現(xiàn)代瀏覽器中得到廣泛支持,但較舊瀏覽器不支持:

總結(jié)
判斷頁(yè)面是否刷新是一個(gè)常見(jiàn)的需求,本文介紹了五種技術(shù)方案。每種方案都有其特定的適用場(chǎng)景和優(yōu)缺點(diǎn)??偨Y(jié)如下:
方案 | 優(yōu)點(diǎn) | 缺點(diǎn) | 瀏覽器兼容性 |
---|
window.name | 簡(jiǎn)單、易跨頁(yè)面保持狀態(tài) | 安全性問(wèn)題,需手動(dòng)清理 | 適用于所有現(xiàn)代瀏覽器 |
sessionStorage | 簡(jiǎn)單,不依賴(lài)復(fù)雜邏輯 | 關(guān)閉標(biāo)簽頁(yè)時(shí)清空 | 支持現(xiàn)代瀏覽器及部分較舊瀏覽器 |
performance.navigation | 直接提供頁(yè)面刷新判斷 | API 正被棄用 | 廣泛支持,但逐漸被廢棄 |
performance.getEntriesByType | 精確判斷加載類(lèi)型 | 較新,舊版瀏覽器不支持 | 僅支持現(xiàn)代瀏覽器 |
beforeunload | 靈活,可處理多種離開(kāi)頁(yè)面的操作 | 部分瀏覽器不支持,尤其是在移動(dòng)端 | 大多數(shù)現(xiàn)代瀏覽器支持 |
不同的方案各有優(yōu)劣,開(kāi)發(fā)者應(yīng)根據(jù)應(yīng)用的目標(biāo)用戶(hù)群體、性能需求和瀏覽器支持情況靈活選擇。如果需要簡(jiǎn)單、跨頁(yè)面的刷新判斷,window.name
是一個(gè)不錯(cuò)的選擇;而在需要更精確、現(xiàn)代化的判斷方式時(shí),performance.getEntriesByType
提供了更高的靈活性。