窗口绑定 POPSTATE

发布于 2024-10-12 03:23:56 字数 187 浏览 3 评论 0原文

鉴于以下情况:

$(window).bind("popstate", function() {
    alert('popstate');
});

首次加载时,FireFox 和 Chrome 会触发警报,但 Safari 不会。这是为什么?其他人看到过这个并知道如何最好地解决这个问题吗?

Given the following:

$(window).bind("popstate", function() {
    alert('popstate');
});

On first load, the alert fires with FireFox and Chrome but not Safari. Why is that? Anyone else seen this and know how to best solve for this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

小女人ら 2024-10-19 03:23:56

请参阅 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

See the code from pjax. pjax is fairly popular open source library now, so the below logic might be the best to avoid this issue.

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

傲娇萝莉攻 2024-10-19 03:23:56

在 webkit 中,popstate 事件在页面加载时触发。为了避免这种情况,这个简单的解决方法对我来说很有效:

每次触发 history.push(...) 时,我都会添加 class historypushedbody-标签:

history.push(...);
$("body").addClass("historypushed");

当我触发 popstate 事件时,我检查此类:

$(window).bind('popstate', function(e) {
 if($("body").hasClass("historypushed")) { 
  /* my code */ 
 } 
});

In webkit the popstate event is fired on page load. To avoid this, this easy work around works for me:

Every time I fire history.push(...) I add the class historypushed to the body-tag:

history.push(...);
$("body").addClass("historypushed");

When I trigger the popstate event, I check for this class:

$(window).bind('popstate', function(e) {
 if($("body").hasClass("historypushed")) { 
  /* my code */ 
 } 
});
伴梦长久 2024-10-19 03:23:56

现在情况发生了逆转。 Chrome 已修复该错误,现在在页面加载时触发 popstate,但 Firefox 4(自 RC 起)已偏离规范,并且 现在不触发 popstate

更新:HTML5 规范于 2011 年进行了更改,规定 popstate 不应在页面加载时触发。从 Firefox 4 和 Chrome 34< 开始,Firefox 和 Chrome 都可以正常运行/a>.

The situation is now reversed. Chrome has fixed the bug and now fires popstate on page load but Firefox 4 (since RC) has departed from the spec and now does not fire popstate!

UPDATE: The HTML5 spec was changed in 2011 to state popstate should not fired on page load. Both Firefox and Chrome now do the right thing as of Firefox 4 and Chrome 34.

小巷里的女流氓 2024-10-19 03:23:56

避免此问题的一个简单方法是将 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();
      }
    });
  }
}

An easy way to avoid this issue is to set the first argument on pushState to true then check against onpopstate. Similar to the pjax example but a bit more straightforward. The below example will run doSomething() for every popstate event except for the first page load.

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();
      }
    });
  }
}
梨涡 2024-10-19 03:23:56

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 的好方法)。

There was a bug in Webkit that incorrectly implemented the "popstate" event. Check out this simple post explaining the problem (cool little show and tell): http://www.bcherry.net/playground/pushstate

My suggestion would be to implement your own "popstate" event tracker for Safari. Something like this:

$(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
});

You could wrap that statement in a browser test to check for safari. Even better see if "popstate" has been fired by the time the DOM is ready and then apply the inner function to replace the implementation. The one thing you don't want to happen is have two popstate events to be fired (duplicating your event handler logic, great way to lock up the UI).

心病无药医 2024-10-19 03:23:56

这个类似问题的答案建议检查 event.state 的布尔值真值popstate 事件处理程序中:

window.addEventListener('popstate', function(event) {
    if (event.state) {
        alert('!');
    }
}, false);

您还可以将回调函数绑定到 popstate 事件,如下所示:

window.onpopstate = callback();

检查 此处 了解有关该解决方案的更多信息

This answer to a similar question suggests to check for boolean truth of event.state in the popstate event handler:

window.addEventListener('popstate', function(event) {
    if (event.state) {
        alert('!');
    }
}, false);

You can also tie your callback function to popstate event like this:

window.onpopstate = callback();

Check here for more information on that solution

画中仙 2024-10-19 03:23:56

这是我的解决方法。

window.setTimeout(function() {
  window.addEventListener('popstate', function() {
    // ...
  });
}, 1000);

This is my workaround.

window.setTimeout(function() {
  window.addEventListener('popstate', function() {
    // ...
  });
}, 1000);
快乐很简单 2024-10-19 03:23:56

我转换@Nobu & @Tamlyn 回答到一个对象中,我还添加了一点
通过添加“window.history.state !== null”来修复。在某些浏览器中
History.state 存在,但它为空,因此它不起作用。

/**
 * 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!

I convert @Nobu & @Tamlyn answers into an object, I also add a little
fix by adding "window.history.state !== null". In some browsers the
history.state exists, but it's null so the it was not working.

/**
 * 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;
	
	...

});

Thanks @Nobu!
Thanks @Tamlyn!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文