歷史返回,若無頁面則跳轉到指定頁面

開頭總要有點廢話html

 

這個功能在原先的js分享中 有簡單的帶過,這裏拎出來 詳細的講解下原理和存在的問題(因爲是運用html5的新API 因此有兼容問題,推薦移動端使用該方法)。html5

功能描述:算法

在瀏覽器中新建標籤頁並指定一個網址,網頁加載完畢後,正常流程下是不容許點擊返回的。由於當前標籤頁的相關歷史記錄是沒有的,因此沒有記錄能夠返回。瀏覽器

應客戶要求,須要在這種狀況下,給他的歷史記錄裏添加一個連接(好比首頁),這樣在新打開的頁面,點擊返回就能夠跳轉到首頁,讓用戶看到系統的各類功能,推廣平臺。安全

 

 

知識要點微信

 

HTML5引進了history.pushState()方法和history.replaceState()方法,它們容許你逐條地添加和修改歷史記錄條目。這些方法能夠協同window.onpopstate事件一塊兒工做。session

 

案例

假設 http://mozilla.org/foo.html 將執行以下JavaScript代碼:優化

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

 

這將讓瀏覽器的地址欄顯示http://mozilla.org/bar.html,但不會加載bar.html頁面也不會檢查bar.html是否存在。google

假設如今用戶導航到了http://google.com,而後點擊了後退按鈕,此時,地址欄將會顯示http://mozilla.org/bar.html,而且頁面會觸發popstate事件,該事件中的狀態對象(state object)包含stateObj的一個拷貝。該頁面看起來像foo.html,儘管頁面內容可能在popstate事件中被修改。url

若是咱們再次點擊後退按鈕,URL將變回http://mozilla.org/foo.html  文檔將觸發另外一個popstate事件,此次的狀態對象爲null。回退一樣不會改變文檔內容。

pushState()方法

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

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

    任何可序列化的對象均可以被當作狀態對象。由於FireFox瀏覽器會把狀態對象保存到用戶的硬盤,這樣它們就能在用戶重啓瀏覽器以後被還原,咱們強行限制狀態對象的大小爲640k。若是你向pushState()方法傳遞了一個超過該限額的狀態對象,該方法會拋出異常。若是你須要存儲很大的數據,建議使用sessionStorage或localStorage。

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

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

注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,傳入的對象使用JSON來進行序列化。從 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)開始,對象使用 結構化拷貝算法來進行序列化。這將容許更多類型的對象可以安全傳入。

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

  • 新的URL能夠是任意的同源URL,與此相反,使用window.location方法時,只有僅修改 hash 才能保證停留在相同的document中。

  • 根據我的須要來決定是否修改URL。相反,設置window.location='#foo',只有在當前hash值不是foo時才建立一條新歷史記錄。

  • 你能夠在新的歷史記錄條目中添加抽象數據。若是使用基於hash的方法,你只能把相關數據轉碼成一個很短的字符串。

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

popstate事件

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

replaceState()方法

history.replaceState()操做相似於history.pushState(),不一樣之處在於replaceState()方法會修改當前歷史記錄條目而並不是建立新的條目。

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

 

實現思路

1.利用popstate事件,監聽點擊返回事件。

2.觸發事件時,判斷當前頁面的歷史記錄 是否有頁面能夠返回。

3.若是沒有頁面能夠返回,則插入兩條記錄:

一、指定的跳轉頁面。

二、空記錄。(使當前頁面不發生變化)

 

實現方法

    //返回以前沒頁面則返回首頁
        function pushHistory() {
            if (history.length < 2) {
                var state = {
                    title: "index",
                    url: getHttpPrefix + "index.html"
                };
                window.history.pushState(state, "index", location.href);
                state = {
                    title: "index",
                    url: ""
                };
                window.history.pushState(state, "index", "");
            }
            //lll("history.state" + history.state)
            //console.log(history.state)  
        }

 

判斷當前history中的記錄個數,因爲頁面加載的時候,瀏覽器會自動push進一個記錄。因此要判斷長度是否小於2.

塞進的state對象是爲了獲取對應的url連接。
注意點:
第一個pushState我將跳轉url放進state對象 方便跳轉操做。第二個參數沒有實際意義,由於如今的瀏覽器基本不適用這個參數。

第三個參數是會替換當前地址欄的連接的,可是頁面不會發生跳轉。(我以前犯了個錯誤,將第三個參數設置爲首頁連接,致使了地址欄更改成首頁連接,以致於在當前頁的連接 都以首頁爲基礎進行跳轉,致使頁面的全部連接都跳轉錯誤了。)

    setTimeout(function () {
            pushHistory()
            window.addEventListener("popstate", function (e) {
                lll("popstate"+window.history.state)
                if (window.history.state != null && window.history.state.url != "") {
                    location.href = window.history.state.url
                }
            });
        }, 300);

 

這段代碼放置在頁面的ready事件中執行,延遲300毫秒是爲了將操做滯後,防止與系統pop事件衝突。
if語句爲了判斷 history是否存在state對象,由於只有知足咱們要求的記錄纔會有咱們添加的state對象 因此 根據這點能夠進行頁面的跳轉操做。
這樣就能夠實現咱們想要的效果。
 

寫在最後

缺點:
     1. 很明顯,就如開頭提到的。只適合支持html5的瀏覽器使用。
     2.因爲插進了兩條記錄 ,因此 相似於 微信這種移動端的返回,須要再點擊兩次返回,才能推出頁面,回到微信聊天窗口,用戶體驗很差。
總結:
這種方法 必定還能夠優化和完善,只是目前個人實力不足,還不足以完善到完美的程度。
但願看到這篇文章的朋友能夠提出本身的看法,意見!
相關文章
相關標籤/搜索