【问题标题】:Can I prevent history.popstate from triggering on initial page-load?我可以防止 history.popstate 在初始页面加载时触发吗?
【发布时间】:2011-07-09 18:19:41
【问题描述】:

我正在开发一个通过 AJAX 提供内容的网站。

如果您单击菜单中的某个项目,内容 div 会更新为 $.get 响应,没什么特别的。

我正在实现history.pushState 以允许使用浏览器的后退/前进按钮进行导航。

我有以下内容可以在历史导航中加载内容:

$(function() {
    $(window).bind("popstate", function() {
        $.getScript(location.href); 
    });
});

问题是,当第一次加载页面时,这个函数会$.getScript所以页面会立即再次加载。第一次加载页面时,它会呈现初始 HTML 视图,然后在第二次加载时,它会呈现 JS 视图,因为它是一个 JS 请求。

如何防止在带有 HTML 请求的页面上触发此事件?

【问题讨论】:

  • 注意:history.popstate 被调用一次 - 在第一页加载时立即调用:这是设计使然。 (在 Chrome 中检查)

标签: javascript jquery history getscript popstate


【解决方案1】:

我使用以下方法更改地址栏并保存当前状态,包括当前 HTML 正文,然后在单击后退按钮时重新加载它,无需任何其他 AJAX 调用。所有内容都保存在您的浏览器中:

<script type="text/javascript">
   $(document).ajaxComplete(function(ev, jqXHR, settings) {
      var stateObj = { url: settings.url, innerhtml: document.body.innerHTML };
      window.history.pushState(stateObj, settings.url, settings.url);
   });

   window.onpopstate = function (event) {
      var currentState = history.state;
      document.body.innerHTML = currentState.innerhtml;
   };
</script>

【讨论】:

    【解决方案2】:

    使用原生 HTML5 History API 您会遇到一些问题,每个 HTML5 浏览器处理 API 的方式都略有不同,因此您不能只编写一次代码就期望它在不实施变通办法的情况下工作。 History.js 为 HTML5 History API 提供了一个跨浏览器 API,如果你想走这条路,还可以为 HTML4 浏览器提供一个可选的hashchange fallback。

    要将您的网站升级为 RIA/Ajax 应用程序,您可以使用以下代码 sn-p: https://github.com/browserstate/ajaxify

    这是较长文章 Intelligent State Handling 的一部分,其中解释了 hashbang、哈希和 html5 历史 API。

    如果您需要任何进一步的帮助,请告诉我 :) 干杯。

    【讨论】:

    • 感谢您提及 History.js。我正要在我们的框架中实现 pushState ,结果可能会被扯掉。
    • 你自己的插件的无耻广告......啧啧......开个玩笑 History.js 现在已经在许多项目中挽救了我的生命(以及大量的工作时间)!
    • 即使是 hasherjs 也能很好地完成这项工作。它在我们当前的生产系统中运行良好。
    • “每个 HTML5 浏览器处理 API 的方式都略有不同”:我很高兴 HTML5 统一了 Web 开发体验并最终将我们带到了 Standardsville。 /s
    【解决方案3】:

    你需要得到event.originalEvent

    // Somewhere in your previous code
    if (history && history.pushState) {
      history.pushState({module:"leave"}, document.title, this.href);
    }
    
    
    $(window).bind("popstate", function(evt) {
      var state = evt.originalEvent.state;
      if (state && state.module === "leave") {
        $.getScript(location.href);
      }
    });
    

    【讨论】:

    • 不测试history.pushState 的存在是否意味着history 的存在?谁能说出为什么对history.pushState 进行测试还不够(用例)?
    • @OliverSchafeld 刚刚看到这个。如果尝试引用history 的属性,但history 不是对象,则会抛出错误。因此,在尝试使用(或检查)其属性之前,您必须验证 history 是否存在(并且是一个对象,如果您不确定)。
    【解决方案4】:

    当页面加载时触发 popstate 事件时,事件对象中将没有 state 属性。这使您可以检查是否为页面加载触发了事件。

    window.onpopstate = function (event) {
      if (event.state) {
        // do your thing
      } else {
        // triggered by a page load
      }
    }
    

    【讨论】:

      【解决方案5】:

      当浏览器首次加载时,它总是会触发一个 popstate 事件。所以你需要确定这个popstate是不是你的。

      当您执行 pushState 时,请确保您有一个状态对象。这样你以后就可以查看了。

      然后在 popstate 处理程序上,检查状态对象:)

      $(function() {
          $(window).bind("popstate", function(data) {
              if (data.state.isMine)
                  $.getScript(location.href); 
          });
      });
      
      // then add the state object
      history.pushState({isMine:true},title,url);
      

      如果您需要更多帮助,请告诉我 :)

      【讨论】:

      • 这已经过时了。浏览器在初始页面加载时不会触发 popstate
      猜你喜欢
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 2019-09-27
      相关资源
      最近更新 更多