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>