ajax實現瀏覽器前進後退-location.hash與模擬iframe

Aajx實現無數據刷新時,咱們會遇到瀏覽器前進後退失效的問題以及URL不友好的問題。javascript

實現方式有兩種css

一、支持onhashchange事件的,經過更新和讀取location.hash的方式來實現html

/*java

  由於Javascript對dom的操做是不持久化的,刷新後就恢復原狀,並且也不保存歷史記錄,也就沒法前進後退來查看歷史了。可是能夠採用「地址欄加hash」技術來解決。
       地址欄中敲入「頁面地址#aaa」就表示跳轉到「頁面地址 」的「aaa」這個頁內錨點(英文叫作hash)。只要改變「aaa」這個錨點內容,瀏覽器就認爲URL變化,也就會放入瀏覽歷史,這樣前進後退問題就解決了。咱們只要把不一樣的AJAX狀態經過不一樣的hash寫到地址欄就能夠了,當頁面加載的時候檢測是否有hash值,有的話就讀取hash進行相應的ajax還原操做。
       location.hash能夠取到或者設置hash的值,當hash改變的時候window.onhashchange事件會被觸發,可是頁面加載的時候哪怕有hash值,onhashchange事件也不會觸發,所以須要在onload事件中也讀取hash進行一樣的處理,保證刷新頁面也能恢復ajax的頁面顯示。
      下面是例子代碼,爲了簡單的突出問題,這裏沒有使用ajax,只是經過dom來修改頁面狀態。點擊文本框,文本框的內容會加1(注意觀察地址欄),刷新頁面後值也仍是增長後的值,並且頁面能夠前進後退。
代碼以下:
[html]
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
    <title>TestDemo</title> 
    <script src="jquery-1.4.2-min.js"></script> 
    <script type="text/javascript"> 
        var processHash = function () { 
            var hashStr = location.hash.replace("#", ""); 
            if (hashStr) $("#txt1").val(hashStr); 
        } 
        $(function () { 
            $("#txt1").click(function () { 
                var i = parseInt($("#txt1").val()); 
                i++; 
                $("#txt1").text(i); 
                location.hash = "#" + i; 
            }); 
            window.onload = processHash; 
            window.onhashchange = processHash; 
        }); 
    </script> 
</head> 
<body> 
    <input type="text" id="txt1" value="1" /> 
</body> 
</html>
node

*/
jquery

二、經過內嵌一個iframe來模擬實現頁面的前進後退,經過iframe的onload事件來實現web

/*ajax

我可應很負責任的告訴你:ajax加載頁面是沒法實現瀏覽器前進和後退功能的, 由於你是直接經過jq 將當前頁面的內容全給替換掉了,而頁面並無跳轉。 不過不是全部事都是絕對的。告訴你一個比較笨可是有比較實用的方法。 就是經過iframe輕鬆解決問題。 首先,你的頁面須要一個隱藏的iframe,且iframe的src對應的是一個任意的html,jsp都行。 當你ajax加載頁面以前,用jq將當前的頁面內容給加載到iframe中去,這個時候,你的iframe中的html元素,就是你當前頁面的html元素沒錯把?這時候再加載你須要ajax加載的頁面。注意,加載頁面的時候千萬不要把這個iframe給覆蓋掉了。。。 再寫一個鍵盤後退按鍵的js監控方法,當按下backspace的時候,將iframe的頁面元素加載出來覆蓋當前頁面,在覆蓋以前記得要把如今的頁面元素覆蓋到iframe中,由於你還有一個前進的操做 前進的操做也是大同小異,說白了就是父頁面元素與iframe中的頁面元素進行對換的操做json

*/
瀏覽器


具體代碼以下,裏面內嵌到的各個頁面,本身創建同名文件便可。


<!DOCTYPE html>

<html>

<head>

<title></title>

<meta charset="utf-8">

<style type="text/css">

.tab {

  display: inline;

}

.tab a {

    color: #fff;

    background: #333;

    padding: 5px 10px;

    border-left: 1px solid #fff;

}

.tab .selected {

    color: red;

    background: #cecece;

}

.content {

    background: #cecece;

    width: 50%;

    margin-top: 5px;

    padding: 10px;

}

pre {

  border: 1px inset gray;

  height: 20em;

}

</style>

</head>


<body >


<script type="text/javascript">


function Ajax (params) {


  if (params) {

      this.XMLHttp = params.XMLHttp; 

      this.method = params.method;

  }

  this.onsuccess = null;

  this.responseType = 'text';


}



Ajax.prototype = {

    getXMLHttp : function () {

        if (!this.XMLHttp) {

             if (window.XMLHttpRequest) {

                // code for IE7+, Firefox, Chrome, Opera, Safari

                  return new XMLHttpRequest();

              } else {// code for IE6, IE5

                  return new ActiveXObject("Microsoft.XMLHTTP");

              }

        }

        return this.XMLHttp;

    },


    request : function (url, data) {

        var self = this;

        try {

            var http = this.getXMLHttp();

            //make a connection to the server ... specifying that you intend to make a GET request 

            //to the server. Specifiy the page name and the URL parameters to send


            var param = '';


            for (var item in data) {

                param += (item + '=' + data[item] + '&');

            }

            url += ( (url.indexOf('?') != -1) ? '&' : '?' ) + param;


            var urlLen = url.length;

            if (url.substr(urlLen - 1, urlLen) == '&') {

                url = url.substr(0, urlLen - 1);

            }


            http.open(this.method, url);

            //assign a handler for the response

            http.onreadystatechange = function() {

                self.response(http);

            }

            //actually send the request to the server

            http.send(null);


        } catch (e) {

            alert(e.message);

        }

    },

    

    get : function (url, data, type, onsuccess) {

        this.method = 'GET';

        this.responseType = type || this.responseType;

        this.onsuccess = onsuccess;

        this.request(url, data);

    },


    post : function (url, data, type, onsuccess) {

        this.method = 'POST';

        this.responseType = type || this.responseType;

        this.onsuccess = onsuccess;

        this.request(url, data);

    },


    response : function(http) {

        if (http.readyState == 4) {

            // 4 = "loaded"

            if (http.status == 200) {

            // 200 = OK

                this.onloadDone(http);

            } else {

                this.onerror('加載失敗');

            }

        }

    },


    onloadDone : function(http) {

        // var data = http.responseText || http.responseXML;

        var data = this.responseType.toLowerCase() == 'xml' ? http.responseXML : http.responseText;

        this.onsuccess.call(this, data);

    },


    onerror : function (message) {

      alert("Problem retrieving XML data");

      if (this.onerror) {

          this.onerror.call(this, message);

      }

    }



}



var Com = {

    isIE6 : (/MSIE 6/.test(navigator.appVersion)),

    hasHashchange : function() {

        if ("onhashchange" in window) {

            return true;

        }

        return false;

    }


};



function PageLoad () {


  this.iframeObj = null;

  this.iframeWin = null;


  this.iframeSrc = this.iframeSrc || 'history.html';

  this.location  = this.location || window.location;


  this.tab = null;

  this.output = null;

  this.tabs = null;


}



PageLoad.prototype = {


    create : function() {

        if (Com.hasHashchange) {

            return;

        }

        if (!this.iframeObj) {

            var ifr = document.createElement_x('iframe');

            ifr.name = 'hashIframe';

            ifr.id   = 'HashIframe';

            ifr.style.display = 'block';

            document.body.appendChild(ifr);

        }


    },


    bindTabEvent : function() {

        var self = this;

        try {

            var tabs = this.tabs;

            for (var i = 0, l = tabs.length; i < l; i++) {

                tabs[i].onclick = function(evt) {

                    var ele = (event.srcElement || event.target || evt.srcElement);

                    var tg = self.toogleTab(ele);

                    return false;

                }

            }

        } catch (e) {

            alert(e);

        } 

    },


    bindHashEvent : function() {

        // bind onhashchange event

        var self = this;

        onhashchange = function() {

            self.pageLoadDone();

        }

    },


    bindIframeEvent : function() {

        var self = this;

        var ifr = self.iframeObj;

        var ifrWind = self.iframeWin;


        if (ifr.attachEvent) {

                ifr.attachEvent('onload', function() {  

                self.iframeLoadDone();

            });

        } else {

              ifr.onload = function() {

                // self.iframeLoadDone.call(this, self);

                self.iframeLoadDone();

            };

        }

    },


    loadDefaultPage : function() {

        var tabname = 'tab1';

        if (Com.hasHashchange) {

            if (this.getHash() == '') {

                // 若是頁面hash值爲空,則更改hash爲初始化的值

                this.setHash(tabname);

            } else {

                // 若是是帶hash訪問則直接經過hash值回溯頁面

                var tab = this.getHash().split('#')[1];

                this.loadDone(tab);

            }

        } else {

            // 若是是不支持onhashchange的瀏覽器,如ie6等採用iframe

            this.iframeObj.src = this.iframeSrc + '?tab=' + tabname;

        }

        

    },


    init : function() {

        if (!this.iframeObj) {

            this.create();

        }


        this.iframeObj = document.getElementByIdx_x('HashIframe');

        this.iframeWin = window.frames['hashIframe'];


        this.tab = document.getElementByIdx_x('tab');

        this.output = document.getElementByIdx_x('output');

        this.tabs = this.tab.getElementsByTagName_r('a');


        this.bindTabEvent();

        if (Com.hasHashchange) {

            this.bindHashEvent();

        } else {

            this.bindIframeEvent();

        }

        this.loadDefaultPage();

    },


    loadDone : function(tab) {

        if ('string' != typeof tab) {

            return;

        }

        try {

            var idx = tab.substr(3) - 1;

            var tabs = this.tabs;


            var _callBack = function(data) {

                output.innerHTML = data;

            }


            this.getContent(tabs[idx], _callBack);

            this.toggle(tabs[idx]);


           



        } catch (e) {

            alert(e.message);

        }


    }, 


    pageLoadDone : function() {

        var hash = this.getHash();

        tab = hash.split('#')[1];

        this.loadDone(tab);

    },


    iframeLoadDone : function() {

        var hash = this.iframeWin.location.search;

        var tab = hash.split('=')[1];

        this.loadDone(tab);


    },


    toggle : function(ele) {

        var tabs = this.tabs;

        var idx = 0;

        for (var i = 0, l = tabs.length; i < l; i++) {

            if (ele != tabs[i]) {

                tabs[i].className = '';

            } else {

                tabs[i].className = 'selected';

            }

        }

    },


    toogleTab : function (ele) {

        // 更改hash,以便瀏覽器監聽

        if ( !(ele.nodeType == 1) ) {

            return false;

        }

        var tabname = ele.getAttribute('tabname');


        this.setSelectedTab(tabname);

        this.toggle(ele);


        return false;

    },   


    setHash : function(hash) {

          //window.location = 'location.html#tab=tab' + idx;

          // window.location.hash = hash;

          window.location.hash = hash;

    },


    getHash : function() {

          var hash = window.location.hash;

          return hash;

    },


    setSelectedTab : function(tabname) {

          if (Com.hasHashchange) {

              this.setHash(tabname);

          } else {

              this.iframeObj.src = this.iframeSrc + '?tab=' + tabname;

          }

    },


    getContentByTarget : function(evt, callBackFun) {

        this.getContent(evt.srcElement);

    },


    getContent : function(ele, callBackFun) {

        var ajax = new Ajax();

        var output = this.output;


        var _callBack = function(data) {

            if (typeof callBackFun == 'function') {

                callBackFun(data);

            } else {

                // output.innerHTML = data;

            }

        };


        output.innerHTML = 'loading...';


        var url = ele.href + '?t=' + Math.random() * 100;

        var data = { item : ele.href, 'href' : ele.href };

        ajax.get(url, data, 'json' , _callBack );

    }


}



window.onload = function() {

    new PageLoad().init();

}



</script>


<br>

<h1>Ajax瀏覽器前進後退</h1>


<h4>

本例經過隱藏location hash來實現前進後退,更改location.hash, 而後經過onhashchange事件來監聽hash變化,經過hash值來還原頁面,不支持onhashchange事件的瀏覽器如ie6仍是須要經過iframe模擬來實現。<a href="location2.html">查看iframe版本</a></h4>



<div class="tab" id="tab">

<a href="data1.txt" tabname="tab1" class="selected">tab1</a><a href="data2.txt" tabname="tab2">tab2</a><a tabname="tab3" href="data3.txt">tab3</a>

</div>

<div class="content">

<pre id="output">

<strong>Loading Ajax接收顯示的內容:</strong>

</pre>

</div>


</body>

</html>

相關文章
相關標籤/搜索