【问题标题】:HTML 5 History API with PopState and AJAX keeps reloading the page带有 PopState 和 AJAX 的 HTML 5 History API 不断重新加载页面
【发布时间】:2019-01-12 09:48:39
【问题描述】:

我目前正在通过 Ajax 将数据加载到页面上,通过 pushState 更新 url,没有错误。并且popstate 将完整的对象返回到控制台——用于查看。

我正处于前进和后退按钮部分工作的地步,这意味着,有时它会在 url 更改时重新显示内容,但大多数情况下它只是简单地重新加载页面,这会阻止应用程序的流畅运行.

一直在努力让事情顺利进行,但没有成功:(

我只是不明白为什么页面不断重新加载并恢复到第一个实例。

我认为这可能与第一次查看页面时设置或未设置状态有关。

下面是我的代码,它会在加载时触发 Ajax 请求,然后在用户更改下拉菜单时更新页面内容。

$(function() {
"use strict";
var $results  = $('#results');

    // First dataset when page loads
    (function(){
      var x = 'https://swapi.co/api/people/';
      var swFirstCall = $.ajax({
        dataType: 'json',
        url: x,
        async: false
      });
      swFirstCall.done(function(data) {
        var template = $('#results_tpl').html();
        var html = Mustache.render(template, data);
        $results.html(html);
      });
    })();

    // New dataset based on selected category
    $(document).on('change', '#categories', function(e){
      e.preventDefault();
      var category = this.value; // get selected value
      var x = 'https://swapi.co/api/' + category + '/';
      var swChangeCall = $.ajax({
        dataType: 'json',
        url: x,
        async: false
      });
      swChangeCall.done(function(data) {
        var template = $('#results_tpl').html();
        var html = Mustache.render(template, data);
        $('#results').html(html);
        console.log("Category: " + category);

        window.history.pushState(
            // data
            // title
            // url
            category,
            category,
            window.location.pathname + '?page=' + category
            );
      });
    });
    window.addEventListener('popstate', function(event) {
          window.location.href = window.location.href;
          console.log(event);
          return(event);
    });
});

非常感谢任何帮助。我搜索了 Stackoverflow 和许多其他资源,但无法理解。

Codepen如果有助于查看代码。

谢谢,巴里

【问题讨论】:

  • 永远不要在 ajax 中使用async: false...这是一种可怕的做法,并且已被浏览器供应商弃用。从来没有任何充分的理由需要它。您应该会在浏览器控制台中看到有关弃用的警告
  • 我删除了async: false 并且错误消失了:) Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. 我意识到.done.then 可以用来代替它。这背后的原因是因为在某些情况下,我需要来自第一个 ajax 请求的特定项目的 id,以便第二个 ajax 请求可以工作。
  • 在这种情况下,在第一次完成后提出第二次请求
  • 如上面提到的@charlietfl 使用.done.then 可以实现吗?
  • 对于像 ajax 这样本质上是异步的东西,你必须学习如何异步处理它们。 then() 是一个承诺回调,承诺是异步的。忘记async:false甚至存在

标签: javascript jquery html html5-history


【解决方案1】:

您想要做的是将datacategory 变量存储在您的历史状态对象中,当您pushState 时。稍后,当您触发popstate 事件(用户前后移动)时,您将拉出该状态。使用您从popstate 事件中获得的值,您将需要重新呈现页面。我对您的 pushState 函数和您的 popstate 处理程序进行了更改,以展示如何做到这一点。最后,您需要遵循其中一个 cmets 中关于删除 ajax 调用中的 async: false 选项的建议 - 您没有理由需要像这样暂停脚本执行的其余部分。

编辑:忘了提到您需要在第一页加载时初始化您的状态对象。使用replaceState 方法来执行此操作,因为您不想创建另一个历史记录条目。相反,您希望修改当前历史记录条目以包括当用户返回初始页面时您希望返回的categorydata。请参阅下面的 swFirstCall.done 方法,其中包含 replaceState 调用。

// ...

swFirstCall.done(function(data) {
  var template = $('#results_tpl').html();
  var html = Mustache.render(template, data);
  $results.html(html);
// initialize history state object
  window.history.replaceState(
    { category: 'Select Category', data  },
    null,
    '',
  );

// ...

window.history.pushState(
  // data
  // title
  // url
  { category, data },
  category,
  window.location.pathname + '?page=' + category
);

// ...

window.addEventListener('popstate', function(event) {
  window.location.pathname + '?page=' + event.state.category;
  var template = $('#results_tpl').html();
  var html = Mustache.render(template, event.state.data);
  $('#results').html(html);
  $('#categories').val(event.state.category);
});

// ..

【讨论】:

  • 优秀 :) 事情正在形成@Kal,工作愉快。我发现的一个小问题。当我尝试返回第一页时,未显示原始内容,并且我看到错误 Uncaught TypeError: Cannot read property 'category' of null
  • @computerbarry 不错。让我在我的原始答案中添加一个编辑来解决这个问题。
  • 完美!你忘了删除最后一个逗号@Kal '', — 一旦我删除它就修复了。再次感谢,这真的很有帮助。我已删除对原始问题所做的编辑。我会看看我是否可以为额外的 Ajax 请求自己构建一些东西。
猜你喜欢
  • 2012-04-03
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多