鉴于以下内容:
$(window).bind("popstate", function() {
alert('popstate');
});
首次加载时,警报会触发FireFox和Chrome,但不会触发Safari。这是为什么?其他人看过这个,知道如何最好地解决这个问题吗?
答案 0 :(得分:45)
请参阅pjax中的代码。 pjax现在是相当流行的开源库,所以下面的逻辑可能是最好的避免这个问题。
var popped = ('state' in window.history), initialURL = location.href
$(window).bind('popstate', function(event) {
// Ignore inital popstate that some browsers fire on page load
var initialPop = !popped && location.href == initialURL
popped = true
if ( initialPop ) return
...
https://github.com/defunkt/jquery-pjax/blob/master/jquery.pjax.js
答案 1 :(得分:17)
在webkit中,popstate事件在页面加载时触发。为了避免这种情况,这个简单的工作对我有用:
每当我点火history.push(...)
时,我都会将class
historypushed 添加到body
- 标记中:
history.push(...);
$("body").addClass("historypushed");
当我触发popstate事件时,我会检查这个类:
$(window).bind('popstate', function(e) {
if($("body").hasClass("historypushed")) {
/* my code */
}
});
答案 2 :(得分:15)
现在情况正好相反。 Chrome修复了该错误,现在在页面加载时触发popstate,但Firefox 4(自RC以来)已脱离规范和now does not fire popstate!
更新:HTML5规范在2011年更改为状态popstate不应在页面加载时触发。从Firefox 4和Chrome 34开始,Firefox和Chrome现在都做对了。
答案 3 :(得分:3)
避免此问题的一种简单方法是将pushState上的第一个参数设置为true,然后检查onpopstate。类似于pjax示例,但更简单一点。下面的示例将为每个popstate事件运行doSomething(),但第一页加载除外。
function setupPopState() {
if (history.popState) {
# immediately replace state to ensure popstate works for inital page
history.replaceState(true, null, window.location.pathname);
$(window).bind('popstate', function(event) {
if (event.originalEvent.state) {
doSomething();
}
});
}
}
答案 4 :(得分:2)
Webkit中存在错误地实现“popstate”事件的错误。看看这个解释问题的简单帖子(很酷的小秀并告诉):http://www.bcherry.net/playground/pushstate
我的建议是为Safari实现自己的“popstate”事件跟踪器。像这样:
$(window).load(function(){
function fire_popstate(){
$(this).trigger("popstate"); // fire it when the page first loads
}
var lasthash = window.location.hash;
setInterval(function(){
var currenthash = window.location.hash;
if(lasthash != currenthash){
fire_popstate();
}
}, 500);//check every half second if the url has changed
});
您可以在浏览器测试中包装该语句以检查safari。甚至更好地看看在DOM准备好之前是否已经触发“popstate”,然后应用内部函数来替换实现。您不希望发生的一件事是要触发两个popstate事件(复制事件处理程序逻辑,锁定UI的好方法)。
答案 5 :(得分:0)
这是我的解决方法。
window.setTimeout(function() {
window.addEventListener('popstate', function() {
// ...
});
}, 1000);
答案 6 :(得分:0)
我转换@Nobu& @Tamlyn回答了一个对象,我也加了一点 通过添加" window.history.state!== null"来修复。在某些浏览器中 history.state存在,但它为null,因此它无效。
/**
* The HTML5 spec was changed in 2011 to state popstate should not
* fired on page load. Chrome(34) & Firefox(4) has fixed the bug but
* some browsers (e.g. Safari 5.1.7) are still fire the popstate on
* the page load. This object created from the Pjax Library to handle
* this issue.
*/
var popstatePageloadFix = {
popped : ('state' in window.history && window.history.state !== null),
initialUrl : location.href,
initialPop : false,
init : function() {
this.initialPop = !this.popped && location.href == this.initialUrl;
this.popped = true;
return this.initialPop;
}
};
$(window).on("popstate", function (event) {
// Ignore initial popstate that some browsers fire on page load
if ( popstatePageloadFix.init() ) return;
...
});

谢谢@Nobu! 谢谢@Tamlyn!
答案 7 :(得分:0)
This answer to a similar question 建议检查event.state
事件处理程序中popstate
的布尔真值:
window.addEventListener('popstate', function(event) {
if (event.state) {
alert('!');
}
}, false);
您还可以将回调函数绑定到popstate
事件,如下所示:
window.onpopstate = callback();
检查 here ,了解有关该解决方案的更多信息