Menu

jquery.history AJAX 無法回到上一頁的解決方案

AJAX 技術的廣泛運用,對網際網路的發展帶來重大變革;透過更新部分頁面即可維護資料,更有效率的反應使用者動作,避免在網路上發送沒有改變的資訊所帶來的頻寬的浪費。但是這樣部分更新的做法,同時也伴隨著缺點,其中受到最多批評的就是瀏覽器後退按鈕的失效;因為 AJAX 並不會更新整個頁面,自然也就無法在瀏覽器中的歷史紀錄留下資訊。

不過這個問題,早在 google 廣泛利用 AJAX 技術的初期,就已經被他們解決囉!雖然必須針對各種瀏覽器做各自不同的處理,但是現在 jQuery 已有網海中的前輩推出簡單使用的 Plugin囉:history plugin,官網本身也是展示網頁;下面稍微介紹一下使用以及運作的流程:

 

首先建立簡單的 AJAX 超連結:

Ajax load<br />
<a href="/article/398-jqueryhistory-ajax-can-not-return-to-the-previous-solution#1" rel="history">load 1</a><br />
<a href="/article/398-jqueryhistory-ajax-can-not-return-to-the-previous-solution#2" rel="history">load 2</a><br />
<a href="/article/398-jqueryhistory-ajax-can-not-return-to-the-previous-solution#3" rel="history">load 3</a><br />

<hr />
Loaded html:<br />
<div id="load"></div>
<hr />

接下來載入 jQuery 以及 jquery.history:

<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="jquery.history.js"></script>

然後插入 JavaScript:

<script type="text/javascript">

// 「上一頁」觸發後執行的函數
function pageload(hash) {
    // 根據傳回的 hash(錨點),AJAX 置換顯示的內容
    if(hash) {
        // 重新讀取指定頁面
        $("#load").load(hash + ".html");
    } else {
        // 如果沒有回傳值,代表已經回到 AJAX 的初始狀態頁,清空顯示的內容
        $("#load").empty();
    }
}

$(function () {
    // 初始化 history plugin,並設定回傳使用的函數
    $.historyInit(pageload);

    // 設定觸發寫入歷史紀錄條件的按鈕事件
    $("a[rel='history']").click(function(){
            // 取得超連結的錨點
        var hash = this.href;
        hash = hash.replace(/^.*#/, '');
        // 點選 AJAX 頁面時,紀錄位置於瀏覽器的歷史紀錄中
        $.historyLoad(hash);
        return false;
    });
});
</script>

大致上的流程為:

1. historyInit() 初始化 history plugin,設定回傳使用的函數;根據使用的函數載入歷史頁面。對 IE 及 safari 採取不同的處理方式,並設定每隔 0.1 秒觸發 historyCheck() 函數。
2. historyCheck() 監聽使用者是否觸發瀏覽器「上一頁」按鈕,對 IE、safari 及其他瀏覽器採取不同的處理方式。觸發「上一頁」按鈕後,依照初始化時設定的回傳函數作相對應的處理。
3. historyLoad() 在觸發 AJAX 更換內容時,寫入新的歷史紀錄,對 IE、safari 及其他瀏覽器採取不同的處理方式。

針對瀏覽器提供的不同處理方式,history plugin 非常貼心的幫我們處理好了;依照官網的說明目前可以相容 IE8、FireFox 4.0、Opera9、Safari 4.0、Chrome 1.0 等多種瀏覽器。所以基本上是不用管 IE 的隱藏 iframe 紀錄,或是 Safari 那一大長串複雜到幾乎看不懂的特殊處理~非常方便!

後記:
原本想要帶入目前專案在用的 ajaxtab,但在 IE 瀏覽器中發現「上一頁」不能流暢的進行;後來才發現可能是 location.hash 與 iframe.location.hash 重複紀錄的關係。因為 IE 已經使用 iframe 進行歷史紀錄,但是 history plugin 仍會利用 location.hash 紀錄。這邊我比較不懂為什麼要紀錄二次,也許有什麼特別的用意吧?因為官網上的範例在 IE 中並沒有這樣的問題,但是 ajaxtab 就會有;如果以後整合 history plugin 的人在 IE 的使用上有問題,請參考不進行 location.hash 紀錄這樣的解決方法吧~

jquery.history.js分析

2008-10-14 12:41
此插件包括兩個全局變量和四個函數。

變量:
historyCurrentHash
當前插件維護的歷史記錄列表的當前瀏覽頁面hash值。

函數:
historyCallback
外部使用時自編的回調函數,函數名是作為historyInit的參數傳遞過來的。
使用回調函數,可以載入特定頁面。

historyInit(callback)
設置歷史記錄的初始狀態,針對IE和SAFARI瀏覽器分別使用不同的方法來實現歷史記錄。
調用historyCallbak來載入歷史頁面。
並設置每隔0.1秒調用historyCheck函數。


historyAddHistory
增加新的歷史記錄(僅針對SAFARI瀏覽器)

historyCheck
檢查是否訪問歷史記錄,根據不同的訪問情況,來調用historyCallback所對應的外調函數來載入對應的頁面

historyLoad(hash)
載入新的頁面,並把頁面加入到歷史記錄列表中。

經過以上分析,使用時要特別增加一個外調函數,用於載入頁面,用此外調函數名作為參數調用historyInit函數,實現插件的初始化並載入對應的頁面。
在任何時候都可以使用historyLoad函數來調用外調函數來載入新頁面,並加入到歷史列表中。