HTML5 history API

HTML5 history API

標籤(空格分隔): JavaScripthtml


DOM window對象經過history對象提供了對瀏覽器歷史的訪問。它暴露了不少有用的方法和屬性,容許你在用戶瀏覽歷史中向前和向後跳轉,同時,從HTML5開始提供了對history棧中內容的操做。html5

1、 在history中跳轉

使用back()forward()go()方法來完成在用戶歷史記錄中向後和向前跳轉。git

// 在history中向後跳轉
window.history.back();
window.history.go(-1);

// 向前跳轉
window.history.forward();
window.history.go(1);

// 當前頁
window.history.go(0);

2、添加和修改歷史記錄中的條目 (pushState()replaceState())

HTML5引入了history.pushState()history.replaceState()方法,他們分別能夠添加和修改歷史記錄條目。這些方法一般與window.onpopstate配合使用。github

使用history.pushState()能夠改變referrer(引用),它在用戶發送XMLHttpRequest請求時在HTTP頭部使用,改變state後建立的XMLHttpRequset對象的referrer都會被改變。由於referrer是標識建立XMLHttpRequest對象時this所表明的window對象中document的URL。ajax

pushState()方法示例api

假設有如下幾個文件瀏覽器

假設在http://demo.com/foo.html中執行了一下js代碼:安全

var stateObj = { foo: 'bar' };
window.history.pushState(stateObj, 'page 2', 'bar.html');

這將使瀏覽器地址欄顯示爲http://demo.com/bar.html,但並不會致使瀏覽器加載bar.html,甚至不會檢查bar.html是否存在。以下圖所示:session

圖1

如今假設用戶又訪問了下面的連接http://demo.com/other.html,而後點擊了返回按鈕。此時,地址欄將顯示http://demo.com/bar.html,同時頁面會觸發popstate事件,事件對象state中包含了stateObj的一份拷貝。頁面自己與foo.html同樣,儘管其在popstate事件中可能會修改自身內容。wordpress

若是咱們再次點擊返回按鈕,頁面URL會變爲http://demo.com/foo.html,文檔對象document會觸發另一個popstate事件,這一次的事件對象state object爲null。這裏也同樣,返回並不改變文檔的內容,儘管文檔在接受popstate事件時可能會改變本身的內容,其內容仍與以前的展示一致。

pushState()方法

pushState()須要三個參數:一個狀態對象,一個標題(目前被忽略)和一個URL(可選的)。

  • 狀態對象

    狀態對象state是一個js對象,經過pushState()建立新的歷史記錄條目。不管何時用戶導航到新的狀態,popstate事件就會被觸發,且該事件的state屬性包含該歷史記錄條目狀態對象的副本。

    狀態對象能夠是能被序列化的任何東西。緣由在於火狐將狀態對象保存在用戶的磁盤上,以便用戶重啓瀏覽器時使用,咱們規定了狀態對象在序列化表示後有640k的大小限制。若是你給pushState()方法傳了一個序列化後大於640k狀態對象,該方法會拋出異常。若是你須要更大的空間,建議使用sessionStorage以及localStorage。

  • 標題

    火狐目前忽略這個參數,但將來可能會用到。傳遞一個空字符串在這裏是安全的,而在未來這是不安全的。二選一的話,你能夠爲跳轉的state傳遞一個短標題。

  • URL

    該參數定義了新的歷史URL記錄。注意,調用pushState()後瀏覽器並不會當即加載這個URL,但可能會在稍後某些狀況下加載這個URL,好比在用戶從新打開瀏覽器時。新URL沒必要須爲絕對路徑。若是新URL是相對路徑那麼它將被做爲相對於當前URL處理。新URL必須與當前URL同源,不然pushState()會拋出一個異常。該參數是可選的,缺省爲當前URL。

某種意義上,調用pushState()與設置widnow.location = '#ff'相似,兩者都會在當前頁面建立並激活新的歷史記錄。但pushState()有如下幾條優勢:

  • 新的URL能夠是與當前URL同源的任意URL。而設置window.location僅當你只修改了哈希值時才保持同一個document。
  • 若是須要,你能夠沒必要改變URL。而設置window.location = '#foo';在當前哈希不是#foo的狀況下,僅僅是新建了一個新的歷史記錄選項。
  • 你能夠爲新的歷史記錄項關聯任意數據。而基於哈希值的方式,則必須將全部相關數據編碼到一個短字符串裏。
  • 假如標題在以後會被瀏覽器用到,那麼這個數據是能夠被使用的(哈希則不能)。

注意pushState()絕對不會觸發hashchange事件,便是是新的URL與舊的URL僅哈希不一樣也不會觸發。

在XUL文檔中,它建立指定的XUL元素。

在其它文檔中,它建立一個命名空間爲URI爲null的元素。

replaceState()方法

history.replaceState()的使用與history.pushState()很是類似,區別在於replaceState()是修改了當前的歷史記錄項而不是新建一個。注意這並不會阻止其在全局瀏覽器歷史記錄中建立一個新的歷史記錄項。

replaceState()的使用場景在於爲了響應用戶操做,你想要更新狀態對象state或者當前歷史記錄的URL。

replaceState()示例

假設http://demo.com/foo.html執行了以下js代碼:

var stateObj = { foo: 'bar' };
window.history.pushState(stateObj, 'page 2', 'bar.html');

假設接着執行了以下代碼:

window.history.replaceState(stateObj, 'page 3', 'bar2.html');

這將會致使地址欄顯示http://demo.com/bar2.html,可是瀏覽器並不會去加載bar2.html甚至不須要檢查bar2.html是否存在。

圖2

假設如今用戶從新導向了http://demo.com/other.html,而後點擊了回退按鈕,這裏地址欄會顯示http://demo.com/bar2.html,再次點擊回退,地址欄顯示foo.html徹底跳過了bar.html

popstate事件

每當活動的歷史記錄項發生變化時,popstate事件都會被傳遞給window對象。若是當前活動的歷史記錄項是被pushState建立的,或者是由replaceState改變的,那麼popstate事件的狀態屬性state會包含一個當前歷史記錄狀態對象的拷貝。

獲取當前狀態

頁面加載時,或許會有個非null的狀態對象。這是有可能發生的,你能夠讀取當前歷史記錄項的狀態對象state,而沒必要等待popstate事件,只須要這樣使用history.state屬性:

var currentState = history.state;

3、window.onpopstate

window.onpopstatepopstate事件在window對象上的事件處理程序。

每當處於激活狀態的歷史記錄條目發生變化時popstate事件就會在對應window對象上觸發。若是當前處於激活狀態的歷史記錄條目事由history.pushState()方法建立,或者由history.replaceState()方法修改過的,則popstate事件對象的state屬性包含了這個歷史記錄條目的state對象的一個拷貝

調用history.pushState()或者history.replaceState()不會觸發popstate事件。popstate事件只會在瀏覽器某些行爲下觸發,好比後退前進或者在js中調用back()等的方法。

當網頁加載時,各瀏覽器對popstate事件是否觸發有不一樣的表現,Chrome和Safari會觸發popstate事件,而FireFox不會。

onpopstate語法

window.onpopstate = funcRef;
// funcRef是個函數名

popdtate事件

假如當前網頁地址爲http://demo.com/example.html,則運行下述代碼後:

window.onpopstate = function(event) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
//綁定事件處理函數. 
history.pushState({page: 1}, "title 1", "?page=1");    //添加並激活一個歷史記錄條目 http://demo.com/example.html?page=1,條目索引爲1
history.pushState({page: 2}, "title 2", "?page=2");    //添加並激活一個歷史記錄條目 http://demo.com/example.html?page=2,條目索引爲2
history.replaceState({page: 3}, "title 3", "?page=3"); //修改當前激活的歷史記錄條目 http://de..?page=2 變爲 http://de..?page=3,條目索引爲3
history.back(); // 彈出 "location: http://demo.com/example.html?page=1, state: {"page":1}"
history.back(); // 彈出 "location: http://demo.com/example.html, state: null
history.go(2);  // 彈出 "location: http://demo.com/example.html?page=3, state: {"page":3}

即使進入了那些非pushState和replaceState方法做用過的(好比http://demo.com/example.html)沒有state對象關聯的那些網頁, popstate事件也仍然會被觸發。

初始打開頁面:
圖3

back一次:
圖4

back二次:
圖5

源碼示例

4、兼容性

Desktop

特性 Chrome Edge FireFox IE Opera Safari
replaceState, pushState 5 Yes 4.0 10 11.50 5.0
history.state 18 Yes 4.0 10 11.50 6.0

5、實例

參見《ajax與HTML5 history pushState/replaceState實例》

Ajax能夠實現頁面的無刷新操做——優勢;可是,也會形成另外的問題,沒法前進與後退。

當執行Ajax操做的時候,往瀏覽器history中塞入一個地址(使用pushState)(這是無刷新的);因而,返回的時候,經過URL或其餘傳參,咱們就能夠還原到Ajax以前的模樣。

效果如圖所示(源碼地址):

圖6

相關文章
相關標籤/搜索