一、前言
上篇提到的‘onbeforeunload’,是一個(gè)很實(shí)用的工具。onbeforeunload可以在用戶(hù)刷新或關(guān)閉頁(yè)面前執(zhí)行自定義的JS事件, 適當(dāng)?shù)眠\(yùn)用可以避免用戶(hù)進(jìn)行誤操作而導(dǎo)致錯(cuò)失珍貴資源(例如填寫(xiě)了很久的表單,不小心刷新頁(yè)面,且表單沒(méi)有實(shí)時(shí)保存功能),且可以有效地減少盈利網(wǎng)站的用戶(hù)流失量,除此之外,開(kāi)發(fā)者還可以進(jìn)行一些有用的操作如一次性處理頁(yè)面數(shù)據(jù)的本地緩存等。
值得注意的是,onbeforeunload并非W3C DOM-Event標(biāo)準(zhǔn)事件,各瀏覽器對(duì) onbeforeunload 事件的支持與觸發(fā)條件實(shí)現(xiàn)有差異(詳情見(jiàn)上篇文章:http://www.lxweimin.com/p/178d9b9adcb3) ,使用onbeforeunload需要考慮各瀏覽器造成的不確定性,有沒(méi)有另一種方式實(shí)現(xiàn)頁(yè)面關(guān)閉前的事件呢?當(dāng)然有。
本文將討論使用window.history實(shí)現(xiàn)頁(yè)面關(guān)閉前事件。
二、window.history基礎(chǔ)用法
DOM對(duì)象通過(guò)history對(duì)象提供對(duì)瀏覽器歷史的訪問(wèn)。功能包括跳轉(zhuǎn)至用戶(hù)歷史瀏覽記錄(鼠標(biāo)在瀏覽器工具欄的前進(jìn)/后退按鈕處右鍵可查看用戶(hù)歷史瀏覽記錄),從HTML5開(kāi)始,還包括操作用戶(hù)瀏覽歷史堆棧的功能。
2.1 跳轉(zhuǎn)到歷史記錄
后退
window.history.back(); //后退到上一個(gè)歷史頁(yè)面,類(lèi)似用戶(hù)在瀏覽器工具欄上點(diǎn)擊返回按鈕
前進(jìn)
window.history.forward(); //前進(jìn)到下一個(gè)歷史頁(yè)面,類(lèi)似用戶(hù)在瀏覽器工具欄上點(diǎn)擊前進(jìn)按鈕
跳轉(zhuǎn)至指定歷史記錄點(diǎn)
指定一個(gè)相對(duì)于當(dāng)前頁(yè)面位置的數(shù)值,用go(數(shù)值)的方法加載歷史頁(yè)面。
例如后退一頁(yè):
window.history.go(-1); //后退到上一個(gè)歷史頁(yè)面,相當(dāng)于window.history.back(); ```
例如前進(jìn)兩頁(yè):
window.history.go(2); //前進(jìn)到下兩個(gè)歷史頁(yè)面,相當(dāng)于執(zhí)行兩次window.history.forward();
##2.2 添加/修改歷史記錄
HTML5新增了history.pushState()與history.replaceState()方法,可用于添加歷史記錄條目與修改歷史記錄條目。
#####history.pushState()
history.pushState()傳入三個(gè)參數(shù):狀態(tài)對(duì)象、標(biāo)題,可選的URL地址,如history.pushState({time:new Date().getTime(), username: 'ice-cream'}, "test", "test-history.html");
【參數(shù)說(shuō)明】
- 狀態(tài)對(duì)象:javascript對(duì)象,可添加多對(duì)鍵值,用于描述當(dāng)前頁(yè)的狀態(tài),狀態(tài)對(duì)象的最大長(zhǎng)度為640k,超出最大長(zhǎng)度則拋出異常。
例如添加時(shí)間戳和用戶(hù)名鍵值,此狀態(tài)對(duì)象為
{
time:new Date().getTime(),
username: 'ice-cream'
}
- 標(biāo)題:字符串,表示將要進(jìn)入的狀態(tài),可傳空字符串。
- 地址:新增歷史條目的url地址,此url地址應(yīng)與當(dāng)前url地址是同源的,否則將拋出異常。
【結(jié)果】
執(zhí)行history.pushState()后,
- 瀏覽器地址欄的地址修改為新增地址
- 瀏覽器不會(huì)在加載新增地址
- 當(dāng)前頁(yè)的狀態(tài)切換為新增的狀態(tài)
#####history.replaceState()
與history.pushState()的用法一樣,但是表示的是修改當(dāng)前的歷史記錄條目。
##2.3 監(jiān)聽(tīng)popstate事件
當(dāng)前歷史記錄狀態(tài)發(fā)生變化時(shí)(換句話(huà)說(shuō),當(dāng)前的頁(yè)面跳轉(zhuǎn)到其他歷史頁(yè)面時(shí)),會(huì)觸發(fā)popstate事件。
注意:當(dāng)網(wǎng)頁(yè)首次加載時(shí),各瀏覽器對(duì)popstate事件是否觸發(fā)有不同的表現(xiàn),Chrome 和 Safari會(huì)觸發(fā)popstate事件, 而Firefox不會(huì)。
【用法】
window.onpopstate = func; //func表示函數(shù)名
//例如
window.onpopstate = function() {
alert('test');
};
//觸發(fā)window.onpopstate
history.go(-1);
#三、用window.history實(shí)現(xiàn)頁(yè)面關(guān)閉前事件
用window.history實(shí)現(xiàn)頁(yè)面關(guān)閉前事件的思路是,在瀏覽歷史堆棧中,插入一條鏈接是當(dāng)前鏈接的歷史條目。
【插入歷史堆棧】
//假設(shè)當(dāng)前頁(yè)面關(guān)閉前需要出現(xiàn)一個(gè)自定義彈框
//若當(dāng)前頁(yè)面的歷史記錄沒(méi)有設(shè)置state屬性,copy1頁(yè)面是第一個(gè)頁(yè)面
if(!history.state || history.state&&history.state.type == "copy1") {
//為當(dāng)前頁(yè)面的歷史記錄添加state屬性為‘copy1’
history.replaceState({
type: 'copy1'
}, '2', location.href);
//新增一個(gè)當(dāng)前頁(yè)面鏈接的歷史記錄,state屬性我哦‘copy2’,copy2是copy1的副本
history.pushState({
type: 'copy2'
}, '2', location.href);
}
【監(jiān)聽(tīng)popstate修改歷史狀態(tài)事件】
window.onpopstate = function(e) {
//若是第一個(gè)頁(yè)面,即copy1
if(history.state && history.state.type && history.state.type == "copy1") {
//顯示彈框mask
document.getElementById('mask').style.display = 'block';
}else {
document.getElementById('mask').style.display = 'none';
}
}
【圖示例】
若當(dāng)前頁(yè)面為copy2時(shí),點(diǎn)擊后退,進(jìn)入和copy2頁(yè)面相同的copy1頁(yè)面。

>參考文章:
1. http://frontenddev.org/article/html-5-pushstate-popstate-operating-history-no-refresh-to-change-the-current-url.html
>2. https://developer.mozilla.org/zh-CN/docs/DOM/Manipulating_the_browser_history
————
前端 · 超大份冰淇淋
紙上得來(lái)終覺(jué)淺,絕知此事要躬行