2013-02-12 85 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