hashchange
與popstate
事件都是瀏覽器歷史記錄API,二者都是HTML5中的API,相對而言popstate
比hashchange
更爲強大。注意這兩種歷史記錄管理都受同源策略的限制,這裏釐清下二者的區別以及相關應用:javascript
hashchange
事件是在瀏覽器URL中hash發生變化後觸發的事件(事件觸發後會在瀏覽器歷史記錄中添加一條記錄),URL中#
後的內容就是hash,它的變化所觸發的hashchange
事件與ajax搭配最多。 按個人理解, 由於hash變化並不會向服務器發生請求,因此若是沒有hashchange
事件,當咱們點擊瀏覽器前進和後退按鈕時,服務器沒法做出反應(由於服務器沒法收到請求), 有了這個事件,就可使用js觸發ajax的新請求讓服務器做出響應。hashchange
事件自己只是監測hash的變化,我認爲目前其主要意義就是與ajax搭配使用從而使得在ajax下歷史記錄前進後退按鈕依然有效。可使用如下簡單的代碼體會下:html
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>hashchange</title> </head> <body onhashchange="alert('Got a hashchange.');"> <a href='#foo'>Click me foo</a> <a href='#bar'>Click me bar</a> </body> </html>
hashchange的文檔mark? hashchangejava
popstate
事件通常與pushState()
和replaceState()
這兩個方法搭配使用, 當用戶點擊瀏覽器的前進後退按鈕時, 支持該事件的瀏覽器就會觸發popState
事件,顧名思義,該事件所pop的正是由pushState()
方法所保存的狀態棧,這裏簡單替下pushState()
方法的語法,引用自MDN文檔(注意該文檔中特地指出了firefox對該方法實現的差別, 好比對title的忽略)?操縱瀏覽器的歷史記錄:ajax
pushState(object,title,url)瀏覽器
狀態對象(state object) — 一個JavaScript對象,與用pushState()方法建立的新歷史記錄條目關聯。不管什麼時候用戶導航到新建立的狀態,popstate事件都會被觸發,而且事件對象的state屬性都包含歷史記錄條目的狀態對象的拷貝。
任何可序列化的對象均可以被當作狀態對象。由於FireFox瀏覽器會把狀態對象保存到用戶的硬盤,這樣它們就能在用戶重啓瀏覽器以後被還原,咱們強行限制狀態對象的大小爲640k。若是你向pushState()方法傳遞了一個超過該限額的狀態對象,該方法會拋出異常。若是你須要存儲很大的數據,建議使用sessionStorage或localStorage。安全
標題(title) — FireFox瀏覽器目前會忽略該參數,雖然之後可能會用上。考慮到將來可能會對該方法進行修改,傳一個空字符串會比較安全。或者,你也能夠傳入一個簡短的標題,標明將要進入的狀態。服務器
地址(URL) — 新的歷史記錄條目的地址。瀏覽器不會在調用pushState()方法後加載該地址,但以後,可能會試圖加載,例如用戶重啓瀏覽器。新的URL不必定是絕對路徑;若是是相對路徑,它將以當前URL爲基準;傳入的URL與當前URL應該是同源的,不然,pushState()會拋出異常。該參數是可選的;不指定的話則爲文檔當前URL。session
每次觸發popstate
事件後,事件對象中state屬性保存了以前經過pushState()
方法壓入的狀態對象。在《javascript權威指南》中例22-3很生動地展現了該用法,這裏將這個例子放在codepen中(點擊連接打開,每次猜想數字後使用瀏覽器前進後退按鈕觀察狀態恢復),一些註釋我從新寫了一下便於理解,可直接在codepen中查看源碼:
DEMO ?基於popstate的猜數字遊戲url
這裏順帶提下replaceState()
,這個方法與pushState()
語法相似,但它是用第一個參數(狀態對象)主動替代當前狀態,它並不會在瀏覽器歷史記錄中增長曆史記錄,這點相似於window.location.replace(url)
firefox
hashchange
只有在hash值改變時才能觸發,而popstate
在支持它的瀏覽器中只要按下「前進」「後退」按鈕就會在Window對象上觸發
popstate
事件能夠是任意同源的url下觸發,也就是說它能夠在example.com/page1 與example.com/page2中均可以觸發,而hashchange
只有在example.com/page1#hash中才能夠(這點暫時是我的理解,並未實驗)
使用事件對象能夠抽象數據,而沒必要將數據變成字符串加在hash中