操縱歷史,利用HTML5 History API實現無重新整理跳轉

藍飛發表於2012-09-05

寫在前面

有一次在上點點網的時候,發現登陸、註冊動畫效果非常華麗,但讓我感到震驚的是頁面竟能夠實現無重新整理跳轉(已改版,觀看此效果可以猛擊此處:GitHub閱FM),回顧了所學的前端知識,似乎沒有任何技術可以實現這一點,於是百度搜羅了一下,才發現這原來是使用HTML5中History API實現的效果,但奈何一直未曾派上用場。直到我的部落格改版時,才將這一技術應用起來。


HTML4中的History API

history這個東西大家應該都不陌生,我們經常使用history.back(-1)來實現後退功能,具體的屬性和方法如下:

屬性

  1. length 歷史的項數。JavaScript 所能管到的歷史被限制在用瀏覽器的“前進”“後退”鍵可以去到的範圍。本屬性返回的是“前進”和“後退”兩個按鍵之下包含的地址數的和。

方法

  1. back() 後退,跟按下“後退”鍵是等效的。
  2. forward() 前進,跟按下“前進”鍵是等效的。
  3. go() 用法:history.go(x);在歷史的範圍內去到指定的一個地址。如果 x < 0,則後退 x 個地址,如果 x > 0,則前進 x 個地址,如果 x == 0,則重新整理現在開啟的網頁。history.go(0) 跟 location.reload() 是等效的。

HTML5中的History API

  1. history.pushState(data, title [, url]):往歷史記錄堆疊頂部新增一條記錄;data會在onpopstate事件觸發時作為引數傳遞過去;title為頁面標題,當前所有瀏覽器都會忽略此引數;url為頁面地址,可選,預設為當前頁地址。
  2. history.replaceState(data, title [, url]) :更改當前的歷史記錄,引數同上。
  3. history.state:用於儲存以上方法的data資料,不同瀏覽器的讀寫許可權不一樣。

瀏覽器相容性

API Chrome Firefox(Geko) Internet Explorer Opera Safari
pushState, replaceState 5 4.0(2.0) -- 11.50 5.0
history.state -- 4.0(2.0) -- 11.50 --
下面是一段檢測瀏覽器是否支援History API的程式碼:
  1. function supports_history_api(){
  2.         return !!(window.history && history.pushState);
  3. }


為什麼要使用History API

在AJAX給我們帶來提高使用者體驗、減少HTTP連線數等好處的同時,也漸漸顯露出一些不足之處,比如:
  1. 無法使用瀏覽器的前進、後退來切換前後資料。
  2. 當我們將瀏覽器位址列中的連結與朋友分享時,可能實際上卻並非我們期望的內容。
  3. 單純地使用AJAX不利於搜尋引擎優化。


實現無重新整理跳轉

上面都是一些理論知識(部分整理於網上),那麼無重新整理跳轉要怎麼實現呢?很簡單的一句程式碼:
  1. history.pushState(null, '', 'newpage.html');
點此檢視效果
如果你使用的是HTML5瀏覽器,並點選了上面的按鈕,那麼應該可以看到,位址列的地址發生了改變,頁面卻沒有重新整理或跳轉。

這是一個最簡單的Demo,雖然實現了地址的無重新整理跳轉,但內容卻沒有對應改變,我們只要在pushState的同時配合上AJAX,一個無重新整理的頁面跳轉效果便完成了,AJAX的實現與本文主題無關,這裡就不再贅述,下面給出的Demo下載會有AJAX部分的程式碼。


相容瀏覽器前進後退效果

簡單地利用history.pushState,雖然可以實現無重新整理地址跳轉,但並沒有解決在瀏覽器中前進後退,內容並沒有相應改變這個問題,此時就需要用到window.onpopstate事件了,當頁面地址發生改變時,便會觸發window物件的onpopstate事件,而我們只要在pushState的同時將當前頁面的引數傳遞給瀏覽器,並在onpopstate事件中作出相應便可以了:
  1. history.pushState({title: '頁面標題', html: '頁面HTML'}, '', 'newpage.html');
  2. window.onpopstate = function(event){
  3.         if(event && event.state){
  4.                 document.title = event.state.title;
  5.                 document.body.innerHTML = event.state.html;
  6.         }
  7. }
當然,還有許多需要考慮的因素,如當頁面開啟時event.state為空,最後一次後退會失效等等,這就需要在頁面載入時先將當前的標題與HTML儲存到變數中,並在當event.state為空時將變數中的內容顯示出來。

還有考慮當連結中含有井號“#”時應如何處理等等……


無重新整理跳轉的具體實現

熬夜將博文寫出,順便將Demo寫成了一個jQuery外掛,精神比較差,基本的功能已經實現,一些細節就暫不考慮了,如果有什麼問題歡迎大家提出。

話說這次的博文也寫的比較語無倫次,還請大家見諒。。

下載地址:http://vdisk.weibo.com/s/bVLeJ
注:由於History API存在安全方面的限制,請在服務端執行方能看到效果


還有話說

如果您願意支援一下的話,歡迎戳一戳我的部落格→http://www.clanfei.com

由於前段時間部落格大規模改版,再加上購置了一級域名,現階段訪問量比較慘淡ToT。。如蒙關照,不勝感激。。



=======================籤 名 檔=======================

原文地址(我的部落格):http://www.clanfei.com/2012/09/1646.html
歡迎訪問交流,至於我為什麼要多弄一個部落格,因為我熱愛前端,熱愛網頁,我更希望有一個更加自由、真正屬於我自己的小站,或許並不是那麼有名氣,但至少能夠讓我為了它而加倍努力。。
=======================籤 名 檔=======================




相關文章