- 理解History Api的使用方式
- 目的是為了解決哪些問題
【01】
【】在使用HTML5的狀態管理機制時,請確保使用pushState()創造的每一個“假”URL,在Web服務器上都有一個真的、實際存在的URL與之對應。否則,單擊“刷新”按鈕會導致404錯誤。
先來看看"history"接口的詳細方法:
interface History {
readonly attribute long length;
readonly attribute any state;
void go(optional long delta);
void back();
void forward();
void pushState(any data, DOMString title, optional DOMString? url = null);
void replaceState(any data, DOMString title, optional DOMString? url = null);
};
為了提高Web頁面的響應速度,越來越多的開發者開始采用單頁面結構(single-page application)的解決方案。
所謂的單頁面結構就是指多個頁面間切換時,不刷新當前整個頁面,更新頁面展示數據,並且相應地改變地址欄中的url,以使用戶可以分享這個url。
如果你使用chrome或者firefox等瀏覽器訪問"github.com、plus.google.com"等網站時,細心的你會發現頁面之間的點擊是通過ajax異步請求的,
同時頁面的URL發生了改變。並且能夠很好的支持瀏覽器前進和后退。
為了用變成方式確定瀏覽器是否支持這個API,可以用下面的一行代碼檢驗:
如果你是用的現代瀏覽器,可以用下面的代碼:
如果你的瀏覽器不支持History API,可以使用history.js代替。
**
if (history.length == 0){
//這應該是用戶打開窗口后的第一個頁面
}
history.length
<html>
<body>
<scripttype="text/javascript"> console.log(history.length); </script>
</body>
</html>
**
history.pushState({name:"魔芋"},"moyu","moyu.html");
console.log(history.state);
**
語法
history.forward()
實例
下面的例子可以在頁面上創建一個前進按鈕:
<html>
<head>
<scripttype="text/javascript">functiongoForward() { window.history.forward() } </script>
</head>
<body>
<inputtype="button"value="Forward"onclick="goForward()" />
</body>
</html>
back() 方法
定義和用法
back() 方法可加載歷史列表中的前一個 URL(如果存在)。
調用該方法的效果等價於點擊后退按鈕或調用 history.go(-1)。
等同於點擊瀏覽器的后退按鈕。
語法:
history.back()
例子:
<html>
<head>
<scripttype="text/javascript">functiongoBack() { window.history.back() } </script>
</head>
<body>
<inputtype="button"value="Back"onclick="goBack()" />
</body>
</html>
**
定義和用法
go() 方法可加載歷史列表中的某個具體的頁面。
語法
history.go(number|URL)
history.go(-2);// 后退兩個歷史記錄,相當於單擊"后退"按鈕兩次
go(1) ;//前進一個;
go(-1) ; /后退一個;
說明
URL 參數使用的是要訪問的 URL,或 URL 的子串。而 number 參數使用的是要訪問的 URL 在 History 的 URL 列表中的相對位置。
也可以給go()方法傳遞一個字符串參數,此時瀏覽器會跳轉到歷史記錄中包含該字符串的第一個位置——可能后退,也可能前進,具體要看哪個位置最近。
如果歷史記錄中不包含該字符串,那么這個方法什么也不做,例如:
//跳轉到最近的wrox.com頁面
history.go("wrox.com");
//跳轉到最近的nczonline.net頁面
history.go("nczonline.net");
history.go(0)相當於刷新當前頁面。
實例
下面例子會加載歷史列表中的前一個頁面:
<html>
<head>
<scripttype="text/javascript">functiongoBack() { window.history.go(-1) } </script>
</head>
<body>
<inputtype="button"value="Back"onclick="goBack()" />
</body>
</html>
但是,瀏覽器並不會真的向服務器發送請求,即使狀態改變之后查詢location.href也會返回與地址欄中相同的地址。
另外,第二個參數目前還沒有瀏覽器實現,因此完全可以只傳入一個空字符串,或者一個短標題也可以。
history.pushState(javascriptObj,"some string","url");
history.pushState({username: "html5"}, "user account", "user.html");
<script> history.pushState({username: "html5"}, "user account", "c.html"); console.log(history); </script>
.html
是否存在,它只是成為瀏覽歷史中的最新記錄。
pushState
方法不會觸發頁面刷新,只是導致
history
對象發生變化,地址欄會有反應。
如果pushState的url參數,設置了一個新的錨點值(即hash),並不會觸發hashchange事件。如果設置了一個跨域網址,則會報錯。
history.pushState({title: 'twitter'}, 'twitter', 'https://twitter.com/moyu')
上面代碼中,pushState想要插入一個跨域的網址,導致報錯。
這樣設計的目的是,防止惡意代碼讓用戶以為他們是在另一個網站上。
在Safari和Chrome中,傳遞給pushState()或replaceState()的狀態對象中不能包含DOM元素。
而Firefox支持在狀態對象中包含DOM元素。
Opera還支持一個history.state屬性,它返回當前狀態的狀態對象。
**
history.replaceState({username: "html5" }, "user account", "user.html");
**
pushState()會創建新的歷史狀態,會發現“后退”按鈕也能使用了。
按下“后退”按鈕,會觸發window對象的popstate事件。
history對象)發生變化時,就會觸發popstate事件。
history.pushState()或history.replaceState()方法時,並不會觸發popstate事件。
history.back()、history.forward()和history.go()方法時才會觸發。
popstate事件只針對同一個文檔,如果瀏覽器歷史的切換,導致加載不同的文檔,該事件也不會被觸發。window.onpopstate = function(event){
console.log(event.state); //輸出pushState()或者replaceState()設置的state信息
}
也可以這樣使用:
window.addEventListener('popstate', function(event) {
console.log('location: ' + document.location)
console.log('state: ' + JSON.stringify(event.state))
})
<div id="click-item"></div>
<div id="result-item"></div>
<script type="text/javascript"> var clickItem = document.getElementById('click-item'); var resultItem = document.getElementById('result-item'); clickItem.onclick = function(){ resultItem.innerHTML = 'clicked!'; history.pushState({note: 'set result'}, '', 'result.html'); } </script>
popstate事件的事件對象有一個state屬性,這個屬性就包含着當初以第一個參數傳遞給pushState()的狀態對象。
popstate事件發生后,事件對象中的狀態對象(event.state)是當前狀態。
EventUtil.addHandler(window, "popstate", function(event){
var state = event.state;
if (state){ //第一個頁面加載時state為空
processState(state);
}
});
得到這個狀態對象后,必須把頁面重置為狀態對象中的數據表示的狀態(因為瀏覽器不會自動為你做這些)。
記住,瀏覽器加載的第一個頁面沒有狀態,因此單擊“后退”按鈕返回瀏覽器加載的第一個頁面時,event.state值為null。
注意:頁面第一次加載的時候,在load事件發生后,Chrome和Safari瀏覽器(Webkit內核)會觸發popstate事件,而Firefox和IE瀏覽器不會。
**
