操縱瀏覽器的歷史記錄


window對象通過history對象提供對瀏覽器歷史記錄的訪問能力。它暴露了一些非常有用的方法和屬性,讓你在歷史記錄中自由前進和后退,而在HTML5中,更可以操縱歷史記錄中的數據。

歷史記錄概覽

可以通過back(),forward()和go()方法在用戶的歷史記錄中前進與后退。

前進與后退

要歷史記錄中后退,只需要這樣做:

window.history.back();

這種行動就非常像用戶在瀏覽器的工具欄上點擊返回按鈕。

類似的,你可以前進,就像在瀏覽器中點擊前進按鈕,像這樣:

window.history.forward();

移動到指定的歷史記錄點

通過指定一個相對於當前頁面位置的數值,你可以使用go()方法從當前會話的歷史記錄中加載頁面(當前頁面位置索引值為0,上一頁就是-1,下一頁為1)。

要后退一頁(相當於調用back()):

window.history.go(-1);

向前移動一頁(相當於調用forward()):

window.history.go(1);

類似的,傳遞參數“2”,你就可以向前移動2頁。

你可以查看length屬性值,了解歷史記錄棧中一共有多少頁:

var numberOfEntries = window.history.length;

添加和修改歷史記錄條目

HTML5引進了history.pushState()方法和history.replaceState()方法,它們允許你逐條地添加和修改歷史記錄條目。這些方法可以協同window.onpopstate事件一起工作。

使用 history.pushState() 會改變 referrer 的值,而在你調用方法后創建的 XMLHttpRequest 對象會在 HTTP 請求頭中使用這個值。referrer的值則是創建 XMLHttpRequest 對象時所處的窗口的URL。

pushState()方法

pushState()有三個參數:一個狀態對象、一個標題(現在會被忽略),一個可選的URL地址。下面來單獨考察這三個參數的細節:

  • 狀態對象(state object) — 一個JavaScript對象,與用pushState()方法創建的新歷史記錄條目關聯。無論何時用戶導航到新創建的狀態,popstate事件都會被觸發,並且事件對象的state屬性都包含歷史記錄條目的狀態對象的拷貝。

    任何可序列化的對象都可以被當做狀態對象。因為FireFox瀏覽器會把狀態對象保存到用戶的硬盤,這樣它們就能在用戶重啟瀏覽器之后被還原,我們強行限制狀態對象的大小為640k。如果你向pushState()方法傳遞了一個超過該限額的狀態對象,該方法會拋出異常。如果你需要存儲很大的數據,建議使用sessionStorage或localStorage。

  • 標題(title) — FireFox瀏覽器目前會忽略該參數,雖然以后可能會用上。考慮到未來可能會對該方法進行修改,傳一個空字符串會比較安全。或者,你也可以傳入一個簡短的標題,標明將要進入的狀態。

  • 地址(URL) — 新的歷史記錄條目的地址。瀏覽器不會在調用pushState()方法后加載該地址,但之后,可能會試圖加載,例如用戶重啟瀏覽器。新的URL不一定是絕對路徑;如果是相對路徑,它將以當前URL為基准;傳入的URL與當前URL應該是同源的,否則,pushState()會拋出異常。該參數是可選的;不指定的話則為文檔當前URL。

某種意義上,調用pushState()有點類似於設置window.location='#foo',它們都會在當前文檔內創建和激活新的歷史記錄條目。但pushState()有自己的優勢:

  • 新的URL可以是任意的同源URL,與此相反,使用window.location方法時,只有僅修改 hash 才能保證停留在相同的document中。
  • 根據個人需要來決定是否修改URL。相反,設置window.location='#foo',只有在當前hash值不是foo時才創建一條新歷史記錄。
  • 你可以在新的歷史記錄條目中添加抽象數據。如果使用基於hash的方法,你只能把相關數據轉碼成一個很短的字符串。

注意pushState()方法永遠不會觸發hashchange事件,即便新的地址只變更了hash。

replaceState()方法

history.replaceState()操作類似於history.pushState(),不同之處在於replaceState()方法會修改當前歷史記錄條目而並非創建新的條目。

當你為了響應用戶的某些操作,而要更新當前歷史記錄條目的狀態對象或URL時,使用replaceState()方法會特別合適。

popstate事件

每當激活的歷史記錄發生變化時,都會觸發popstate事件。如果被激活的歷史記錄條目是由pushState所創建,或是被replaceState方法影響到的,popstate事件的狀態屬性將包含歷史記錄的狀態對象的一個拷貝。

讀取當前狀態

在頁面加載時,可能會包含一個非空的狀態對象。這種情況是會發生的,例如,如果頁面中使用pushState()或replaceState()方法設置了一個狀態對象,然后用戶重啟了瀏覽器。當頁面重新加載時,頁面會觸發onload事件,但不會觸發popstate事件。但是,如果你讀取 history.state 屬性,你會得到一個與  popstate 事件觸發時得到的一樣的狀態對象。

你可以直接讀取當前歷史記錄條目的狀態,而不需要等待popstate事件:

var currentState = history.state;

window.onpopstate

概述

window.onpopstatepopstate事件在window對象上的事件句柄.

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

調用history.pushState()或者history.replaceState()不會觸發popstate事件. popstate事件只會在其他瀏覽器操作時觸發, 比如點擊后退按鈕(或者在JavaScript中調用history.back()方法).

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

語法

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

popstate事件

假如當前網頁地址為http://example.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://example.com/example.html?page=1,條目索引為1
history.pushState({page: 2}, "title 2", "?page=2");    //添加並激活一個歷史記錄條目 http://example.com/example.html?page=2,條目索引為2
history.replaceState({page: 3}, "title 3", "?page=3"); //修改當前激活的歷史記錄條目 http://ex..?page=2 變為 http://ex..?page=3,條目索引為3
history.back(); // 彈出 "location: http://example.com/example.html?page=1, state: {"page":1}"
history.back(); // 彈出 "location: http://example.com/example.html, state: null
history.go(2);  // 彈出 "location: http://example.com/example.html?page=3, state: {"page":3}

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

 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM