46

我已经阅读了有关 Stack Overflow 的几个问题/答案,并在 Google 上搜索了这个问题,event.state但除了null.

我知道它不适用于 jQuery 事件,但是当我做这样的事情时:

window.onpopstate = function (e) {
     console.log(e.state)
}

使用类似于 jQuery.ajax 成功调用的方式

history.pushState({ lastUrl: data.State }, data.Title, data.UrlKey);

Chrome (v19) 或 Firefox (v12) 都不返回空值?我错过了什么吗?它只是没有完全实施吗?

4

7 回答 7

63

e.state指被推送的倒数第二个状态。您需要至少两次推送状态e.state才能不是null。这是因为您应该在您的网站第一次加载时保存状态,然后每次更改状态时保存。

于 2012-08-07T10:55:36.810 回答
16

我认为这个问题需要更清楚的解释,因为其他答案中的“倒数第二个状态”这句话可能会导致混淆。

当我们执行 history.pushState 时,我们正在将一个新状态推入历史堆栈,它成为当前状态(正如我们从导航栏 url 中看到的那样。)

window.onpopstate 事件意味着顶部历史状态正在被弹出(从堆栈中取出),因此 e.state 现在将指向堆栈中新的新顶部状态(因为导航栏将指向上一个网址)。

于 2015-11-03T18:48:04.277 回答
4

我在同一个问题上挣扎了好几个小时。太多小时了。onpopstate -handler 的状态参数为空,即使我在单击后退按钮之前已多次调用 pushState()。

我还观察到我的 onclick-handler 调用 pushState() 导致 onpopstate -handler 被触发。我相信 onpopstate -handler 只有在用户点击我在网上阅读的后退按钮时才会被调用。但就我而言,情况似乎并非如此。

浏览器可能有错误吗?似乎不太可能,因为我在 Chrome 和 FireFox 上都有相同或类似的问题。但有可能。或者也许有一个“规范中的错误”太复杂而无法正确实施。没有公开的单元测试显示这应该如何工作。

最后我找到了一个解决方案,之后一切都开始工作了。是将这两个调用放入我的 onload-handler 中:

pushState (myInitialState, null, href);
pushState (myInitialState, null, href);

所以我必须在 onload-handler 中进行相同的 push-state() 调用 TWICE!之后,我的 onpopstate -handler 开始获取状态不是 null 的参数,而是我之前作为参数传递给 pushState() 的状态。

我真的不明白为什么它现在可以工作,为什么当我只调用一次 pushState 时它不能更早。

我想了解为什么它现在可以工作,但我已经花了太多时间让它工作。如果有人在网上有很好的示例代码的参考,这将是很好的。

于 2018-05-26T02:23:03.483 回答
1

如果您曾经了解过撤消/重做堆栈,将会很有帮助,如下图所示。

在此处输入图像描述

事实上,历史是这样保存在堆栈中的。您当前的状态来自当前堆栈项,假设有一个指向它的指针;当您调用 时history.back(),指针指向堆栈的较旧项,onpopstate事件的状态与history.state顺便说一句相同。您将只获得指针当前指向的项目,由 修改history.replaceState或添加history.pushState

这个过程也解释了为什么history.length不改变,因为它代表了整个堆栈的长度。当您调用history.go(1)时,指针会移回较新的项目。

当指针在栈的中间位置时,调用history.pushState会导致指针上面的所有项都弹出,并新增一项,也可以看到history'length变化。

于 2019-02-21T09:07:41.437 回答
1

history.state与当前页面相关联,因此可以forwardback。要获取第一个历史的状态,您可以使用history.replaceState放置在第一个历史的状态。

window.history.replaceState(currentState, document.title)
于 2021-08-09T13:06:50.603 回答
1

哇,这里的所有答案都令人困惑。

  • 您需要推送或替换初始状态。
  • popstate 不会给你倒数第二个状态,而是最后一个状态。
  • 当然不需要两次推送初始状态。

我认为每个人都感到困惑的是,event.state它将保留您在调用中设置为第一个 ( data) 参数的任何值history.pushState()。如果您将其设置为null,那么您肯定event.state也会为空。

为什么不需要推送初始状态?

初始状态就在您的事件中,只是没有data设置,event.state所以null. 您正在寻找重定向回初始页面的内容只是document.location(因为在 时popstate,我们已经在该位置)。

如果您想要完全控制,最好用一些有意义的data集合替换初始状态,这样您就可以确定它是您期望的状态,而无需比较文档 url。

于 2021-12-05T20:44:11.973 回答
0

正如 Jaco Briers 所提到的,为了popstate按照我们认为应该工作的方式工作,我们需要首先存储初始状态,以便在您单击浏览器的后退按钮时返回。这是一个使用 jQuery 的示例实现:

示例代码

$(window).on({
  // Store initial state
  'load': function() {
    window.history.pushState({
      'html': '<div id="ajax-content">' + $('#ajax-content').html() + '</div>'
    }, '', document.URL);
  },
  // Handle browser Back/Forward button
  'popstate': function(e) {
    var oState = e.originalEvent.state;
    if (oState) {
      $('#ajax-content').replaceWith(oState.html);
    }
  }
});

...

// Update AJAX content
var sUrl = 'https://www.example.com/category?id=123&format=ajax';
$.ajax({
  type: 'GET',
  url: sUrl,
  success: function(sHtml) {
    $('#ajax-content').replaceWith(sHtml);
    window.history.pushState({
      'html': sHtml
    }, '', sUrl);
  }
});
于 2020-03-17T19:05:11.347 回答