【问题标题】:window bind POPSTATE窗口绑定 POPSTATE
【发布时间】:2011-06-08 23:00:44
【问题描述】:

鉴于以下情况:

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

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

【问题讨论】:

    标签: javascript jquery html history


    【解决方案1】:

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

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

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

    window.onpopstate = callback();
    

    查看 here 了解有关该解决方案的更多信息

    【讨论】:

      【解决方案2】:

      我将@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!

      【讨论】:

        【解决方案3】:

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

        更新:HTML5 规范于 2011 年更改为声明 popstate 不应在页面加载时触发。从 Firefox 4 和 Chrome 34 开始,Firefox 和 Chrome 现在都做了正确的事情。

        【讨论】:

        • HTML5 规范在 2011 年更改为声明 popstate 不应在页面加载时触发。投票code.google.com/p/chromium/issues/detail?id=63040 是让 Chrome 重新符合标准的最佳方式。 Google 两年前就知道 Chrome 的行为不正确。
        【解决方案4】:

        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】:

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

          每次我触发history.push(...) 时,我都会将class historypushed 添加到body-tag:

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

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

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

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

              这是我的解决方法。

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

              【讨论】:

              • 这是做什么的?也许与其发布everywhere,不如让它解释一次。
              • @drozzy 当然!这段代码为 popstate 事件添加了一个新的事件监听器(1 秒后)。使用这种方法,popstate 事件不会在页面加载时触发。
              • @Baggz,根据a demo of Dive into html51 ms比较合适。
              【解决方案8】:

              查看 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

              【讨论】:

                猜你喜欢
                • 2013-01-19
                • 2012-05-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-06-25
                • 2013-03-19
                • 2016-03-23
                • 2011-07-19
                相关资源
                最近更新 更多