2013-02-12 78 views
14

我想更改html而無需重新加載。我這樣做:history.pushState - 不工作?

$('#left_menu_item').click(function(e) { 
    if (!!(window.history && history.pushState)) { 
     e.preventDefault(); 
     history.pushState(null, null, newUrl); 
    } 
}); 

它工作正常。但如果我想回到「返回」按鈕 - 瀏覽器更改網址上,但它不會重新加載頁面。爲什麼?

+0

據我所知HTML5歷史API不實際修改頁面內容。我甚至不知道如何將HTML越做越pushState的 – 2013-02-12 03:12:23

+0

改變是什麼瀏覽器,你做你的實驗?這種行爲在不同的瀏覽器上可能會有不同的結果 – abbood 2013-02-12 04:14:34

+0

Chrome 24.0和Firefox 17.0。行爲是一樣的。 – indapublic 2013-02-12 04:56:45

回答

33

此行爲是預期的並且與操縱歷史堆棧的specifications一致。

這是一個比較複雜的問題來解釋。但簡單地認爲它是這樣的:用戶在歷史堆棧上使用推送歷史記錄(使用pushState等)的任何歷史記錄都不值得從頁面加載,因爲它被認爲是假的(用戶生成的)歷史記錄條目。

爲什麼? 這種行爲是一件好事,並與開發人員更多地控制頁面而不被強制重新加載它的意圖一致(將它想像爲ajax:您可以執行以前只能通過頁面重新加載數據但現在,如果你想,當你處理window.onpopstate事件以模仿單擊後退按鈕..你可以簡單地調用location.reload()時重新加載頁面的行爲,你可以做到這一點,而無需使用XMLHttpRequest對象重新加載頁面)..


怎麼樣? 這可能是你的問題的範圍,但我只想把它放在那裏來形容我們在說什麼關於

讓我通過使用現有的例子here解釋(摘錄的文字將斜體):

假設http://mozilla.org/foo.html執行下面的JavaScript:

var stateObj = { foo: "bar" }; 
history.pushState(stateObj, "page 2", "bar.html"); 

這將導致URL欄以顯示http://mozilla.org/bar.html,但不會導致瀏覽器加載bar.html甚至檢查bar.html是否存在。

認爲這是因爲你在歷史堆棧中創建一個與實際頁面加載無關的條目..而是一個'假'頁面加載(即你只是使用JavaScript來操縱DOM並插入html)..

現在假設用戶現在導航到http://google.com,然後單擊回來。此時,URL欄將顯示http://mozilla.org/bar.html,該頁面將獲得一個狀態對象包含stateObj副本的popstate事件。該頁面本身看起來像foo.html,儘管該頁面可能會在popstate事件期間修改其內容。

這裏要說的是,一個bar.html是假的歷史條目,對原http://mozilla.org/foo.html的頂部位於..所以你會看到在URL http://mozilla.org/bar.html但內容將屬於foo的(在這個例子通知我們當我們推動bar.html時沒有操縱dom的內容..如果我們喜歡你的例子,那麼內容也會顯示出來)。這裏的關鍵是頁面重新加載! ..因爲我們服務的歷史堆棧上有genuin條目的頁面(即使在url上,我們顯示的是與歷史堆棧上的假條目關聯的url)。

也將此討論與手動處理popstate事件的頁面分開..這是一個不同的故事,只會使事情複雜化。

如果我們再次點擊,URL將變爲http://mozilla.org/foo.html,文檔將會得到另一個popstate事件,這次是一個null狀態對象。在這裏,返回並不會改變文檔內容與上一步中的內容,儘管文檔可能在接收到popstate事件後手動更新其內容。

這裏..頁面不會加載! ..這是因爲我們正在從一個虛假的歷史堆棧條目轉移到真正的(並且真正的已經在上一步加載..所以頁面重新加載,就是這樣)。

就是這樣的例子。這個概念有點難以解釋,我鼓勵你通過點擊真實和假冒頁面的組合來測試你的代碼,你會看到一個模式,當頁面實際加載時,它不會。

+3

很好的解釋:) – 2013-05-27 06:23:51

+1

感謝恭喜@MandeepJain :) – abbood 2013-05-27 07:07:41

+3

了不起的工作,很好的答案和細節! – Masha 2015-08-07 18:55:52

13
window.onpopstate = function(event) {  
    if(event && event.state) { 
     location.reload(); 
    } 
} 

這是我用:)

+0

優雅的解決方案:) – indapublic 2014-02-02 07:27:52

+0

或使用window.location = window.location; – Jimbob 2014-02-02 18:48:57