history對象保存着用戶上網的歷史記錄,從窗口被打開的那一刻算起。因爲安全方面的考慮,開發人員沒法獲得用戶瀏覽器的URL,但藉由用戶訪問過的頁面列表,能夠在不知道實際URL的狀況下實現後退和前進。本文將詳細介紹BOM中的history對象javascript
history.length屬性保存着歷史記錄的URL數量。初始時,該值爲1。若是當前窗口前後訪問了三個網址,history.length屬性等於3html
因爲IE10+瀏覽器在初始時返回2,存在兼容性問題,因此該值並不經常使用java
history.length // 初始時,該值爲1 history.length // 訪問三個網址後,該值爲3
history對象提供了一系列方法,容許在瀏覽歷史之間移動,包括go()、back()和forward()跨域
【go()】瀏覽器
使用go()方法能夠在用戶的歷史記錄中任意跳轉。這個方法接收一個參數,表示向後或向前跳轉的頁面數的一個整數值。負數表示向後跳轉(相似於後退按鈕),正數表示向前跳轉(相似於前進按鈕)緩存
//後退一頁 history.go(-1) //前進一頁 history.go(1); //前進兩頁 history.go(2);
go()方法無參數時,至關於history.go(0),能夠刷新當前頁面安全
//刷新當前頁面 history.go(); //刷新當前頁面 history.go(0);
【back()】服務器
back()方法用於模仿瀏覽器的後退按鈕,至關於history.go(-1)session
【forward()】ide
forward()方法用於模仿瀏覽器的前進按鈕,至關於history.go(1)
//後退一頁 history.back() //前進一頁 history.forward()
若是移動的位置超出了訪問歷史的邊界,以上三個方法並不報錯,而是靜默失敗
[注意]使用歷史記錄時,頁面一般從瀏覽器緩存之中加載,而不是從新要求服務器發送新的網頁
HTML5爲history對象添加了兩個新方法,history.pushState()和history.replaceState(),用來在瀏覽歷史中添加和修改記錄。state屬性用來保存記錄對象,而popstate事件用來監聽history對象的變化
[注意]IE9-瀏覽器不支持
【pushState()】
history.pushState()方法向瀏覽器歷史添加了一個狀態。pushState()方法帶有三個參數:一個狀態對象、一個標題(如今被忽略了)以及一個可選的URL地址
history.pushState(state, title, url);
state object —— 狀態對象是一個由pushState()方法建立的、與歷史紀錄相關的javascript對象。當用戶定向到一個新的狀態時,會觸發popstate事件。事件的state屬性包含了歷史紀錄的state對象。若是不須要這個對象,此處能夠填null
title —— 新頁面的標題,可是全部瀏覽器目前都忽略這個值,所以這裏能夠填null
URL —— 這個參數提供了新歷史紀錄的地址。新URL必須和當前URL在同一個域,不然,pushState()將丟出異常。這個參數可選,若是它沒有被特別標註,會被設置爲文檔的當前URL
假定當前網址是example.com/1.html,使用pushState方法在瀏覽記錄(history對象)中添加一個新記錄
var stateObj = { foo: 'bar' }; history.pushState(stateObj, 'page 2', '2.html');
添加上面這個新記錄後,瀏覽器地址欄馬上顯示example.com/2.html,但並不會跳轉到2.html,甚至也不會檢查2.html是否存在,它只是成爲瀏覽歷史中的最新記錄。假如這時訪問了google.com,而後點擊了倒退按鈕,頁面的url將顯示2.html,可是內容仍是原來的1.html。再點擊一次倒退按鈕,url將顯示1.html,內容不變
總之,pushState方法不會觸發頁面刷新,只是致使history對象發生變化,地址欄的顯示地址發生變化
若是pushState的url參數,設置了一個新的錨點值(即hash),並不會觸發hashchange事件,即便新的URL和舊的只在hash上有區別
若是設置了一個跨域網址,則會報錯。這樣設計的目的是,防止惡意代碼讓用戶覺得他們是在另外一個網站上
// 報錯 history.pushState(null, null, 'https://twitter.com/hello');
【replaceState()】
history.replaceState方法的參數與pushState方法如出一轍,不一樣之處在於replaceState()方法會修改當前歷史記錄條目而並不是建立新的條目
假定當前網頁是example.com/example.html
history.pushState({page: 1}, 'title 1', '?page=1'); history.pushState({page: 2}, 'title 2', '?page=2'); history.replaceState({page: 3}, 'title 3', '?page=3'); history.back() // url顯示爲http://example.com/example.html?page=1 history.back() // url顯示爲http://example.com/example.html history.go(2) // url顯示爲http://example.com/example.html?page=3
【state】
history.state屬性返回當前頁面的state對象
history.pushState({page: 1}, 'title 1', '?page=1'); history.state// { page: 1 }
【popstate事件】
每當同一個文檔的瀏覽歷史(即history對象)出現變化時,就會觸發popstate事件
須要注意的是,僅僅調用pushState方法或replaceState方法,並不會觸發該事件,只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用javascript調用back()、forward()、go()方法時纔會觸發。另外,該事件只針對同一個文檔,若是瀏覽歷史的切換,致使加載不一樣的文檔,該事件也不會觸發
使用的時候,能夠爲popstate事件指定回調函數。這個回調函數的參數是一個event事件對象,它的state屬性指向pushState和replaceState方法爲當前URL所提供的狀態對象(即這兩個方法的第一個參數)
window.onpopstate = function (event) { console.log('location: ' + document.location); console.log('state: ' + JSON.stringify(event.state)); };
上面代碼中的event.state,就是經過pushState和replaceState方法,爲當前URL綁定的state對象
這個state對象也能夠直接經過history對象讀取
var currentState = history.state;
默認狀況下,瀏覽器會在當前會話(session)緩存頁面,當用戶點擊「前進」或「後退」按鈕時,瀏覽器就會從緩存中加載頁面
瀏覽器有一個特性叫「往返緩存」(back-forward cache或bfcache),能夠在用戶使用瀏覽器的「後退」和「前進」按鈕時加快頁面的轉換速度。這個緩存中不只保存着頁面數據,還保存了DOM和javascript的狀態;其實是將整個頁面都保存在了內存裏。若是頁面位於bfcache中,那麼再次打開該頁面時就不會觸發load事件
[注意]IE10-瀏覽器不支持
【pageshow】
pageshow事件在頁面加載時觸發,包括第一次加載和從緩存加載兩種狀況。若是要指定頁面每次加載(不論是不是從瀏覽器緩存)時都運行的代碼,能夠放在這個事件的監聽函數
第一次加載時,它的觸發順序排在load事件後面。從緩存加載時,load事件不會觸發,由於網頁在緩存中的樣子一般是load事件的監聽函數運行後的樣子,因此沒必要重複執行。同理,若是是從緩存中加載頁面,網頁內初始化的JavaScript腳本(好比DOMContentLoaded事件的監聽函數)也不會執行
[注意]雖然這個事件的目標是document,但必須將其事件處理程序添加到window
pageshow事件有一個persisted屬性,返回一個布爾值。頁面第一次加載時或沒有從緩存加載時,這個屬性是false;當頁面從緩存加載時,這個屬性是true
(function(){ var showCount = 0; window.onload = function(){ console.log('loaded'); } window.onpageshow = function(e){ e = e || event; showCount ++; console.log(e.persisted,showCount + 'times'); } })();
[注意]上面的例子使用了私有做用域,以防止變量showCount進入全局做用域。若是單擊了瀏覽器的「刷新」按鈕,那麼showCount的值就會被重置爲0,由於頁面已經徹底從新加載了
【pagehide】
與pageshow事件對應的是pagehide事件,該事件會在瀏覽器卸載頁面的時候觸發,並且是在unload事件以前觸發。與pageshow事件同樣,pagehide在document上面觸發,但其事件處理程序必需要添加到window對象
[注意]指定了onunload事件處理程序的頁面會被自動排除在bfcache以外,即便事件處理程序是空的。緣由在於,onunload最經常使用於撤銷在onload中所執行的操做,而跳過onload後再次顯示頁面極可能就會致使頁面不正常
pagehide事件的event對象也包含persisted屬性,不過其用途稍有不一樣。若是頁面是從bfcache中加載的,那麼persisted的值就是true;若是頁面在卸載以後會被保存在bfcache中,那麼persisted的值也會被設置爲true。所以,當第一次觸發pageshow時,persisted的值必定是false,而在第一次觸發pagehide時,persisted就會變成true(除非頁面不會被保存在bfcache中)
window.onpagehide = function(e){ e = e || event; console.log(e.persisted); }