在瀏覽器中改變地址欄url,將會觸發頁面資源的從新加載,這使得咱們能夠在不一樣的頁面間進行跳轉,得以瀏覽不一樣的內容。但隨着單頁應用的增多,愈來愈多的網站採用ajax來加載資源。由於異步加載的特性,地址欄上的資源路徑沒有被改變,隨之而來的問題就是頁面的狀態沒法被保存。這致使咱們難以經過熟悉的方式(點擊瀏覽器前進/後退按鈕),在先後的頁面狀態間進行切換。html
爲了解決ajax頁面狀態不能返回的問題,人們想出了一些曲線救國的方法,好比利用瀏覽器hash的特性,將新的資源路徑假裝成錨點,經過onhashchange事件來改變狀態,同時又避免了瀏覽器刷新。但這樣始終顯得有些hack。ajax
如今HTML5規範爲 window.history引入了兩個新api,pushState 和 replaceState,咱們可使用它很方便的達到改變url不重載頁面的目的api
——引用於https://blog.csdn.net/helloxiaoliang/article/details/73850428瀏覽器
location.hash和location服務器
當一個頁面的(顯示)狀態被改變時,能夠經過location.hash實現刷新頁面後或者copy頁面的URL再打開後保持狀態而不還原。session
當hash只有一個#時,location.hash返回空字符串;當hash不止一個#時,location.hash返回#以及#後面的部分。異步
當 一個window的 hash (URL 中 # 以及#後面的部分,可經過location.hash返回)改變時就會觸發 hashchange 事件。網站
window.location屬性返回一個有文檔的當前位置的信息的Location對象。google
語法:var oldLocation = location; location = newLocation;url
不管何時,當一個新值被賦予location對象,一個文檔將經過這個URL被加載,就像是location.assign()被這個URL調用了同樣。
location.reload(true);:強制從服務器從新加載當前頁面。
location.replace('http://example.com/#' + location.pathname);:將經過使用replace()方法插入location.pathname的值進hash來從新加載頁面。注意,這replace()方法和字符串的replace()方法不是一個東西。
location.search = sData;:經過改變search屬性來發送一個字符串數據給服務器。"?Some%20data"添加到當前的URL,而後URL被送到服務器(若是服務器沒有采起動做,當前文檔就用這個改變的search字符串從新加載)。
操縱瀏覽器歷史
DOM window 對象經過 history 對象提供了對瀏覽器歷史的訪問。
window.history.back();:和用戶點擊瀏覽器回退按鈕的效果相同。相似的還有window.history.forward();和window.history.go(Num);。另外,window.history.length; 能夠得到歷史堆棧中頁面的數量。執行history.back()或history.forward()後會觸發 window.onpopstate事件。
pushState()方法毫不會致使hashchange 事件被激活,就算新的URL和舊的只在hash上有區別。
history.pushState() 方法和history.replaceState()方法分別能夠添加和改變歷史實體。這兩個方法要和window.onpopstate事件一塊兒用。push和pop說明它們的行爲就像棧。popstate事件會被觸發當一個文檔的激活的歷史實體改變。若是激活的歷史實體是由history.pushState()建立的,或者是被history.replaceState()改變過,那popstate事件的state屬性(即e.state)會包含一個該激活的歷史實體的sate對象的副本;若是不是,那e.state的值爲null。調用history.pushState()方法和history.replaceState()方法不會觸發popstate事件,the popstate event is only triggered by performing a browser action, such as clicking on the back button (or calling history.back() in JavaScript)。如今的瀏覽器加載頁面時都不會觸發popstate事件了(之前有的瀏覽器會)。
舉個例子。history.pushState({ foo: "bar" }, "", "bar.html");會使地址欄的http://mozilla.org/foo.html變成http://mozilla.org/bar.html,可是不會使瀏覽器加載http://mozilla.org/bar.html,甚至都不會使瀏覽器檢查http://mozilla.org/bar.html是否存在。假設用戶在這個頁面導航到了http://google.com,而後點擊瀏覽器的回退按鈕。這時,地址欄變成http://mozilla.org/bar.html,並且瀏覽器會加載http://mozilla.org/bar.html。若是這時你讀取history.state,你會獲得{ foo: "bar" }(即history.pushState()的第一個參數)。這時popstate事件不將被觸發(?),由於頁面是經過被加載而顯示的(頁面加載時觸發的是load事件而不是popstate事件)。若是咱們再點擊回退按鈕,纔會回到http://mozilla.org/foo.html,這時文檔會得到一個popstate事件(能夠經過這個事件改變文檔內容),且history.state是null。總之,history.pushState()會添加一個歷史實體並激活它(也就是如今的頁面變成新添加的歷史實體了),但暫時仍是顯示原來的歷史實體,只有當再次回到這個頁面時(包括刷新,可是要注意刷新不會觸發popstate事件哦,只有前進和後退會觸發)纔會顯示新添加的歷史實體。
history.pushState()接收三個參數,一個對象(用做state),一個字符串(用做標題,可是目前都被瀏覽器忽略),一個字符串(用做URL,是可選的):
·state會成爲history.pushState()添加的歷史實體的屬性,能夠用history.state得到。傳入state的參數要能字符串化,好比能用JSON字符串化,由於火狐瀏覽器會把state這個對象存在用戶的磁盤,以便當用戶重啓瀏覽器時state這個對象能恢復實際傷並不能恢復。state這個對象字符串化後的大小有限制(火狐是640K),若是須要更多的空間,你應該使用sessionStorage 和/或localStorage。
·第二個參數傳入空的字符串便可。
·傳入的URL能夠是相對的也能夠是絕對的。若是是相對的,它將相對於當前的URL被解析。傳入的URL必須和當前的URL同源。若是不傳入URL,則會被設置爲當前的URL。
總之,調用pushState()和設置window.location = "#foo"(設置hash,與window.location.hash = "#foo"等效,且window.可省略)很像,二者都建立了並激活了一個新的歷史實體。可是前者由如下優勢:
1. 新的URL能夠是任何和當前URL同源的URL,而設置window.location讓你智能呆在同一個文檔裏,由於你只改變了hash。
2. 你能夠不改變URL而建立新的歷史實體,而經過設置window.location = "#foo";建立一個新的歷史實體則必需要求當前的hash不是#foo。
3. 你能夠在state中放入任何數據,而用hash就只能在URL末尾放入短字符串形式的數據。
history.replaceState()和history.pushState()很像,除了是改變當前的歷史實體而不是建立一個新的。當你像更新當前的歷史實體的state對象或URL來響應用戶的行爲時,replaceState()至關有用。