深入学习 History 对象管理浏览器会话历史
History對象允許我們操作瀏覽器會話歷史,即加載當前頁面的標簽頁窗口或frame窗口的訪問歷史。之前有同學咨詢我如何實現攔截用戶跳轉頁面并強制用戶返回首頁后重新請求頁面,于是有了本篇博客的主題,本篇深入介紹瀏覽器會話歷史的操作,在最后對比加載頁面的幾種不同方式,并提供一個實例給讀者把玩。
屬性
-
History.length
只讀的,其值為一個整數,標志包括當前頁面在內的會話歷史中的記錄數量,比如我們通常打開一個空白窗口,length為0,再訪問一個頁面,其length變為1。
-
History.scrollRestoration
允許web應用在會話歷史導航時顯式地設置默認滾動復原,其值為auto或manual。
-
History.state
只讀,返回代表會話歷史堆棧頂部記錄的任意可序列化類型數據值,我們可以以此來區別不同會話歷史紀錄。
方法
-
History.back()
返回會話歷史記錄中的上一個頁面,等價于window.history.go(-1)和點擊瀏覽器的后退按鈕。
-
History.forward()
進入會話歷史記錄中的下一個頁面,等價于window.history.go(1)和點擊瀏覽器的前進按鈕。
-
History.go()
加載會話歷史記錄中的某一個頁面,通過該頁面與當前頁面在會話歷史中的相對位置定位,如,-1代表當前頁面的上一個記錄,1代表當前頁面的下一個頁面。若不傳參數或傳入0,則會重新加載當前頁面;若參數超出當前會話歷史紀錄數,則不進行操作。
-
History pushState()
在會話歷史堆棧頂部插入一條記錄,參數包括,任意可序列化的object對象數據(可選),頁面標題(可選),頁面URL(非空)。
目前,Firefox忽略頁面標題參數。
-
History.replaceState()
更新會話歷史堆棧頂部記錄信息,包括特定的任意可序列化的object對象數據(可選),頁面標題(可選),頁面URL。
值得注意的是,無論是replaceState()方法還是pushState()方法,其更新或添加會話歷史記錄后,改變的只是瀏覽器關于當前頁面的標題和URL的記錄情況,并不會刷新或改變頁面展示。
window.history
window的history是只讀屬性,該屬性返回History對象的一個引用,支持我們操作瀏覽器會話歷史記錄。
出于安全考慮,History對象不允許我們通過JavaScript代碼訪問其他會話歷史記錄中其他頁面的URL,但是它允許我們在不同頁面間進行導航。
onpopstate事件
HTML5中,提供history.pushState()和history.replaceState()方法,支持我們添加或更新會話歷史記錄,另外還提供window.onpopstate事件支持我們對該操作進行監聽。
pushState()
pushState()方法接收三個參數,一個state對象,一個頁面標題,一個URL:
狀態對象:
頁面標題:
頁面URL:
pushState()方法可以改變URL地址欄,在會話歷史堆棧頂部插入一條新會話記錄,如:
var stateObj = { foo: "bar" };history.pushState(stateObj, "page 2", "bar.html");假如當前訪問頁面http://blog.codingplayboy.com,則執行以上js代碼后,瀏覽器地址欄變為http://blog.codingplayboy.com/bar.html,頁面展示并沒有變化,隨后,
- 若我們點擊瀏覽器的后退按鈕,頁面也不會變化,只是瀏覽器的地址欄URL變換為之前的http://blog.codingplayboy.com;
- 若我們點擊跳轉到http://blog.codingplayboy.com/about.html,然后再點擊瀏覽器的后退按鈕,則頁面會回退到http://blog.codingplayboy.com/bar.html頁面,且在該頁面觸發popstate事件,會向事件回調傳入一個之前定義的stateObj的復制值參數;
- 我們可以在popstate事件回調中執行我們的任務,但是必須知道的是,只有當當前頁面DOM加載完成(即DOMContentLoaded事件發生)后才會觸發popstate事件。
- pushState()方法不會觸發hashchange事件,即使URL的hash片段值改變。
replaceState()
與history.pushState()方法相比,history.replaceState()方法不創建新的會話歷史,而是更新當前會話歷史記錄,如更新當前會話記錄的狀態對象或URL。
popstate事件
每次會話記錄變換激活都會在window上觸發popstate事件,如果激活的會話記錄是通過replaceState()更新的或使用pushState()方法創建的,popstate事件對象的state屬性值就是該會話記錄狀態對象的一個副本。
location.reload()與location.replace()小結
我們知道location.reload()和location.replace()方法還有直接設置location值,都可以重新加載頁面,但是這三種方式也是有區別的:
reload()
-
語法
location.reload(beForceGet)
-
參數
beForceGet,可選,值為true或false;默認為false,表示是否從客戶端緩存讀取當前頁;為true時,則從服務端重新請求頁面(相當于F5刷新和history.go(0)方法)。
replace()
-
語法
location.replace(url)
-
參數
一個相對或絕對URL,使用相對于當前頁URL解析后的URL替換當前會話記錄的URL,效果與使用history.replaceState()方法修改URL相同;
-
對比reload()
location.reload()會取客戶端的緩存頁面,但是location.replace(url)總是重新請求加載url指向的頁面。
location賦值
-
語法
location.href = url;
或
location.assign(url); -
說明
可以為location直接設置一個URL值,該值等效于使用pushState()修改URL,會創建一條新會話記錄。
攔截用戶返回頁面及強制請求新頁面實例
點此傳送到實例訪問地址
首先,我們進入首頁index.html,并點擊任意跳轉,跳轉到第二頁a.html(當然在實際應用中可以是任意頁面),然后點擊返回,我們會發現,并沒有返回到我們訪問的首頁,而是進入了我們設置的攔截頁,具體如何實現的呢,因為我們在第二頁中編寫JavaScript代碼實現:
;(function() {window.onpopstate = function(event) { console.log(event.state); location.replace('replace.html'); }; history.pushState({name: '驚鴻'}, '', 'a.html?history=1'); })();我們調用pushState()方法創建了一條新會話記錄(該會話URL為a.html?history=1,仔細看瀏覽器地址欄變URL變成了a.html?history=1,),并綁定了popstate事件回調,當瀏覽器返回時,會退回到上一條會話記錄,即a.html會話,然后觸發popstate事件,在事件回調函數中,我們調用location.replace('replace.html')將a.html頁面跳轉至replace.html(可以是任意同源頁面),這就實現了攔截用戶跳轉;隨后,再次點擊返回,會返回到我們訪問的第一個頁面,我們查看NetWork請求會發現不同于之前返回的頁面(請求狀態碼為304),其狀態碼是200,說明是一次新的請求,這是因為在replace.html頁面中,加了如下代碼:
;(function() {window.onpopstate= function(event) { console.log(event.state); document.location.replace(location.href); }; })();我們在popstate事件回調中,使用location.replace()方法強制刷新了當前頁面;當我們在攔截頁點擊返回時,會回退到第一頁會話,URL為index.html,然后觸發popstate事件,執行document.location.replace(location.href);刷新頁面。
pushState()和replaceState()能做的比我們想象的要多,本文比較詳細的對其進行了介紹,有興趣的同學可以參考MDN或玩w3c,進行更深入的學習,也可以搜索PJAX,即PushState和Ajax,同時使用這兩個工具,可以極大加快網站響應速度。
歡迎移步我的個人博客
總結
以上是生活随笔為你收集整理的深入学习 History 对象管理浏览器会话历史的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20个寓言故事超短
- 下一篇: resteasy经验谈