【问题标题】:window.onpopstate, event.state == null?window.onpopstate, event.state == null?
【发布时间】:2012-06-21 00:09:21
【问题描述】:

我已经阅读了有关 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) 都不返回 null 以外的任何内容?我错过了什么吗?只是没有完全实现吗?

【问题讨论】:

  • @Derek 您提供的问题是关于在页面加载时触发 popstate。澄清一下,在任何时候 popstate 触发时,从 pushState 函数(即上例中的 lastUrl)发送的数据都不会在事件对象中可用,这是我要询问的问题

标签: javascript html dom-events


【解决方案1】:

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

【讨论】:

  • 解决了我在这里问的问题stackoverflow.com/questions/13107147/… ...如果您可以在这里为我的问题写下答案,我可以接受。
  • 一般评论:我建议不要重载函数window.onpopstate = function (e) {,而是简单地“听”它window.addEventListener("popstate", function(event) {...因为否则你会取消其他你没有重新执行的实现-写。
  • 在下面查看我对同一问题的描述。每次用户(我)单击链接时,我都会多次调用 pushState。但是状态仍然始终为空。当我在 ONLOAD 处理程序中“至少两次”调用 pushState () 时,它才变为非 null。我不明白为什么从 onclick 处理程序多次调用它并没有使它工作。它可能与 pushState() 的第三个参数的值错误有关吗?谁知道。可能。但是在 onload 处理程序中调用 pushState() 两次解决了这个问题。
  • 只是添加到上面的答案:而不是调用 pushState 两次,这会在历史记录中添加 2 个条目,我更喜欢在加载时调用 replaceState 以获取我想要的状态。然后后续的pushState 调用按预期工作。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    我为同样的问题苦苦挣扎了好几个小时。 太多小时了。 onpopstate -handler 的状态参数 即使我调用了 pushState() 也为 null 多次点击后退按钮。

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

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

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

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

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

    我真的不明白为什么它现在有效并且 为什么当我只调用 pushState 时它没有更早 一次。

    我想了解为什么它现在可以工作,但我 已经花了太多时间在这个得到 它工作。如果有人提到好 在线示例代码解释了它 会很好。

    【讨论】:

    • 在我的情况下,popState 会经常收到 null 状态(并非总是如此)。确保有一个额外的初始 pushState 调用似乎已经解决了这个问题。
    【解决方案4】:

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

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

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

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

    【讨论】:

    • 这解释了null 值如何?
    【解决方案5】:

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

    window.history.replaceState(currentState, document.title)
    

    【讨论】:

      【解决方案6】:

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

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

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

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

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

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

      【讨论】:

        【解决方案7】:

        正如 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);
          }
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-11-17
          • 1970-01-01
          • 2022-07-09
          • 1970-01-01
          • 2011-12-13
          • 2018-02-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多