Javascript 窗口绑定 POPSTATE

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4688164/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 13:38:00  来源:igfitidea点击:

window bind POPSTATE

javascriptjqueryhtmlhistory

提问by AnApprentice

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?

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

采纳答案by Tamlyn

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!

现在情况发生了逆转。Chrome 已修复该错误,现在在页面加载时触发 popstate 但 Firefox 4(自 RC 起)已脱离规范,现在不触发 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.

更新:HTML5 规范在 2011 年更改为状态 popstate 不应在页面加载时触发。与 Firefox 4 和Chrome 34一样,Firefox 和 Chrome 现在都在做正确的事情。

回答by Nobu

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.

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

https://github.com/defunkt/jquery-pjax/blob/master/jquery.pjax.js

回答by lohsie

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

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

Every time I fire history.push(...)I add the classhistorypushedto the body-tag:

每次我开火时,history.push(...)我都会将classhistorypushed添加到body-tag 中:

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

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

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

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

回答by HuffMoody

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.

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

回答by Shakakai

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

Webkit 中存在错误实现“popstate”事件的错误。查看这个解释问题的简单帖子(很酷的小节目并告诉):http: //www.bcherry.net/playground/pushstate

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

我的建议是为 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
});

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).

您可以将该语句包装在浏览器测试中以检查 safari。最好看看在 DOM 准备好时“popstate”是否已经被触发,然后应用内部函数来替换实现。您不希望发生的一件事是要触发两个 popstate 事件(复制您的事件处理程序逻辑,这是锁定 UI 的好方法)。

回答by Baggz

This is my workaround.

这是我的解决方法。

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

回答by Roy Shoa

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.

我将@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;
 
 ...

});

Thanks @Nobu! Thanks @Tamlyn!

谢谢@Nobu!谢谢@Tamlyn!

回答by Wilt

This answer to a similar questionsuggests to check for boolean truth of event.statein the popstateevent handler:

This answer to a similar question建议检查事件处理程序event.state中的布尔值popstate

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


You can also tie your callback function to popstateevent like this:

您还可以将回调函数绑定到这样的popstate事件:

window.onpopstate = callback();

Check herefor more information on that solution

在这里为对解决方案的更多信息