用戶通過“點擊觸發”,“操作歷史”,“直接訪問URL”的方式修改當前URL。這三種觸發方式會使瀏覽器做出不同的行為
html5提供了兩種方式在頁面中操作歷史
- history.pushState(state, title, url)
- 將當前URL和history.state加入到history中,並用新的state和URL替換當前, 不會造成頁面刷新。
- history.replaceState(state, title, url)
- 用新的state和URL替換當前, 不會造成頁面刷新。
- history.state
- 如果當前URL不是通過pushState或者replaceState產生的,那么history.state是null。
提供檢測歷史記錄變化的事件popstate
-
每當處於激活狀態的歷史記錄條目發生變化時,popstate事件就會在對應window對象上觸發.-
如果當前處於激活狀態的歷史記錄條目是由history.pushState()方法創建,或者由history.replaceState()方法修改過的, 則popstate事件對象的state屬性包含了這個歷史記錄條目的state對象的一個拷貝.
-
- 調用
history.pushState()或者history.replaceState()不會觸發popstate事件. popstate事件只會在瀏覽器操作如點擊前進or后退按鈕(JS調用也可), URL中"#"后面的字符串改變時觸發.
利用這一特性, 就可以處理無刷新頁面的前端后退,保存歷史操作的頁面狀態啦。
demo一下
<a href="#1">text1</a>
<a href="#2">text2</a>
<a href="#3">text3</a>
<a href="#4">text4</a>
<a href="#5">text5</a>
<script>
window.addEventListener('popstate', function(event) {
readState(event.state);
});
for(i=0;i<5;i++){
var stateObject = {id: i};
var title = "Wow Title "+i;
var newUrl = "/my/awesome/url/"+i;
history.pushState(stateObject,title,newUrl);
}
function readState(data){
alert(data.id);
}
</script>
hashchange
在URL的參數列表(及URL中"#"號后面的所有字符串)發生變化的時候觸發, hash的變化不會觸發瀏覽器請求資源,因此天然可以來處理頁面內無刷新導航 。
兼容如下:
- IE8+ | FF3.6+ | Safari5+ | Chrome | Opera 10.6+ 支持hashchange
- event對象有兩個屬性:oldURL和newURL, FF3.6+ Chrome Opera支持 oldURL 和 newURL
在IE6、7下可以采用定時循環檢測或者采用添加隱藏iframe的方式來解決, 如:
if( ('onhashchange' in window) && ((typeof document.documentMode==='undefined') || document.documentMode==8)) {
// 瀏覽器支持onhashchange事件
window.onhashchange = hashChangeFire; // TODO,對應新的hash執行的操作函數
} else {
// 不支持則用定時器檢測的辦法
setInterval(function() {
// 檢測hash值或其中某一段是否更改的函數, 在低版本的iE瀏覽器中通過window.location.hash取出的指和其它的瀏覽器不同,要注意
var ischanged = isHashChanged();
if(ischanged) {
hashChangeFire(); // TODO,對應新的hash執行的操作函數
}
}, 150);
}
總結
在前端的實際應用場景中,如果頁面局部刷新,不改變URl,在頁面刷新、前進、后退,或者想分享一個具體的頁面狀態鏈接的時候, 就會體驗特別差。
如果要改變url進行局部更新, 這時檢測到URL的變化就非常重要。
我們可以利用改變hash觸發hashchange或者兼容方案定時檢測hashchange的方法,來達到更改頁面Url並同時更新頁面局部顯示狀態的效果。 不過有時會期望單頁中的URL和服務端開發時的URL風格比較一致,會在document上監聽鏈接的點擊,利用html5 history提供的API來改變URl, 並調用相應的處理函數來達到不刷新頁面同時更新頁面局部狀態的目的
以上已經能好的解決了頁面內功能無刷新導航的功能, 但還有一個需要注意的是, 第一次訪問鏈接或者刷新頁面URL時, 需要后端配合將本頁的所有URL做一下重定向。 另外首次從不同的URL進入時,也需要在前端根據URL進行一下手動的分發。
