HTML5 onpopstate 页面加载时

10

我正在使用新的HTML5 onpopstate事件。在Firefox 4中,当页面加载时会触发window.onpopstate事件,而在Webkit中似乎并不是这种情况。

哪种行为是正确的?


1
这个问题现在在Chrome Canary中已经被修复了,预计它将在下一个版本(或两个版本)的Chrome中得到修复。 - Agamemnus
@Agamemnus,很奇怪,在我的页面加载时没有触发。 - Pacerier
在什么条件下? - Agamemnus
6个回答

10

1
这个问题在Firefox和Webkit之间似乎存在一些歧义。目前,当页面加载时,Webkit不会触发onpopstate事件。 - epoch
6
2011年后访问此页面的开发人员请注意,HTML5规范已做出修改,使得在初始页面加载时不应触发“popstate”事件。FireFox、IE10等浏览器都表现出了正确的行为;但Chrome(以及可能的Safari)则没有。请投赞成票支持https://code.google.com/p/chromium/issues/detail?id=63040,让Chrome回到符合标准的状态。 - Dave
2
@Dave:Safari Mobile仍然(截至2014年8月)在初始页面加载时触发此操作。 - Jonas Byström
1
@Dave,这个问题早就被解决了 https://code.google.com/p/chromium/issues/detail?id=63040#c47 - Pacerier
@Dave:你能否提供一个W3C规范的链接,说明popstate事件不应该在页面加载时触发吗?我找不到相关信息... - smohadjer
我说过它不应该在初始页面加载时触发。请参见http://www.w3.org/TR/2012/CR-html5-20121217/browsers.html#history-traversal - 步骤12-14。这也在https://code.google.com/p/chromium/issues/detail?id=63040#c50中有解释。 - Dave

4

在页面加载时触发onpopstate是正确的做法,WebKit也很快会采用这种行为。WebKit 534.7 (Chrome 7.0.517.44)现在已经采用了这种方式。

我在Chrome上报告了一个错误,但事实证明这是期望的行为;这是处理某些后退/前进按钮操作所必需的。有关更多讨论和链接,请参见code.google.com上的此错误报告

我仍在努力想出一个好的代码模式来处理onpopstate事件处理程序。


我也遇到了这个问题(在WebKit中触发onpopstate会导致第一次加载时出现双重页面加载)。我通过添加一些逻辑来解决这个问题 - 例如,在第一次ajax请求后仅添加onpopstate监听器。 - benbyford

3
我不知道你是否在询问这个问题,但我的解决方案是为了处理仅限ajax的 onpopstate 事件,需要在window.onload上设置一个名为refreshed的变量,并将其设置为false,在history.pushState调用时将其设置为true。然后在 onpopstate 处理程序中,只有在refreshedfalse时才进行操作。

看起来很傻,事实上也确实如此,但我无法做得更好。


在Firefox中,当单击浏览器的“后退”按钮时,window.onload也会被触发,因此最好在其他地方初始化refreshed - jamix

3

我刚解决了这个问题,而修复方法实际上非常简单。Firefox在初始页面加载时不会触发onpopstate事件。当你触发一个popstate事件后,在page.load操作上返回false或阻止默认行为,就可以解决问题。

祝好运。

这里有一个实际例子:www.thecoffeeshopnyc.com

// Write in a new handler for Firefox, which does not fire popstate on load.
// Modern Webkit browsers fire popstate on load. The event handler below fires the controller
$(window).load(function () {
    if ($.browser.mozilla) {
        // Your func.
    }
})

// Add the event listener. If the above is false, it will still run as intended in normal browsers.
window.onpopstate = function() {
    // Your func.
}

当Chrome决定修复这个问题时,这将会出现错误。浏览器检测是解决问题的快速方法,但应该使用特性检测来避免难以发现的错误。 - Agamemnus

1
浏览器在页面加载时处理popstate事件的方式不同。Chrome和Safari总是在页面加载时发出popstate事件,但Firefox不会。
这段引用来自Mozilla的文档:https://developer.mozilla.org/en-US/docs/DOM/window.onpopstate 我倾向于支持Mozilla的系统。页面加载不需要触发额外的popstate事件,因为状态不是被弹出,而是第一次加载。
我猜Webkit之所以这样做是为了方便...在我所有的实现中,将处理程序延迟到初始popstate事件之后始终是一个不便之处。
与其这样(使用伪函数):
AddEventHandler(window, 'popstate', OnPopState);

我需要做类似这样的事情:

AddLoadEvent(window.setTimeout(function() 
    { 
        AddEventHandler(window, 'popstate', OnPopState); 
    },0));

1

如果有人感兴趣,我已经想出了一个不错的模式来处理onpopstate(这段代码假设使用jQuery,功能检测的部分被简化了):

$(function() {

  // 1. Add initial state to current history record on page load.
  var href = location.href;
  history.replaceState({"href": href}, null, href);

  // 2. Now attach the popstate handler.
  window.onpopstate = function(ev) {

    // Raised on page load this event will still contain no state.
    var state = ev.state;
    if (state && state.href) {

      // 3. Add your logic, use `state` and `state.href` as you see fit.          

    }
  };

});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接