19

我想在不重新加载的情况下更改 html。我这样做:

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

它工作正常。但是,如果我想使用“返回”按钮返回 - 浏览器会更改以前的 url,但它不会重新加载页面。为什么?

4

2 回答 2

42

这种行为是预期的,并且符合操作历史堆栈的规范

这是一个解释起来相对复杂的问题。但简而言之,可以这样想:用户在历史堆栈上推送的任何历史条目(使用 pushState 等)在您从中移动时都不值得页面加载,因为它被认为是假的(用户生成的)历史条目。

为什么? 这种行为是一件好事,并且与让开发人员对页面有更多控制权而不被迫重新加载它的意图一致(将其想象为 ajax:您可以做以前只能通过页面重新加载才能完成的事情,例如获取数据,但是现在您可以在不使用XMLHttpRequest对象重新加载页面的情况下执行此操作).. 如果您想模仿单击后退按钮时重新加载页面的行为.. 您可以location.reload()在处理window.onpopstate事件时简单地调用


如何? 这可能超出了您的问题范围,但我只是想把它放在那里来描述我们在说什么

让我在这里使用现有示例进行解释(摘录文本将用斜体显示):

假设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,页面将获得一个 popstate 事件,其 state 对象包含 stateObj 的副本。页面本身看起来像 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 事件,这次是一个空状态对象。在这里,返回也不会改变上一步中的文档内容,尽管文档可能会在接收到 popstate 事件后手动更新其内容。

在这里..页面将无法加载!.. 那是因为我们正在从一个虚假的历史堆栈条目转移到真实的历史堆栈条目(并且真实的历史堆栈条目已经在上一步中加载......所以页面重新加载,就是这样)。

就是这个例子。这个概念有点难以解释,我鼓励你通过点击真实和虚假页面的组合来测试你的代码,你会看到页面实际加载和不加载的模式。

于 2013-02-12T05:19:10.270 回答
13
window.onpopstate = function(event) {    
    if(event && event.state) {
        location.reload(); 
    }
}

这就是我使用的:)

于 2014-02-02T07:02:58.900 回答