【问题标题】:HTML5 History API: "popstate" not called when navigating back from another pageHTML5 History API:从另一个页面返回时未调用“popstate”
【发布时间】:2018-08-01 10:31:29
【问题描述】:

我必须维护一个带有 AJAX 搜索表单(比如说书籍)的网站,并且我希望搜索结果成为浏览器历史记录的一部分。

所以我设置了 "popstate" 事件处理程序

window.addEventListener('popstate', function(e) {
    alert("popstate: " + JSON.stringify(e.state));
});

并在 AJAX 请求成功时调用 pushState()

var stateObj = { q: "harry potter" };
window.history.pushState(stateObj, "Result", "/search");

那么我的点击流是:

  1. 使用搜索表单加载页面 - NORMAL 请求 - 路径为 /
  2. 输入查询字符串并提交表单 - AJAX 请求 - 路径更改为 /search
  3. 单击搜索结果 - 正常请求 - 路径更改为 /books/harry-potter

  1. 当我现在通过单击浏览器后退按钮返回返回时,我希望“popstate”事件会被相应的状态对象触发。但什么也没发生。 - 路径更改为 /search

  1. 当我再次返回时,我收到popstate: null 的警报 - 路径更改为 /

  2. 然后当我向前之后,我得到popstate: {"q":"harry potter"} - 路径更改为/search


因此,重要的 popstate 事件(带有查询字符串的事件)仅在前进时触发,而在后退时不会触发。

这是因为我从一个站点导航回来,该站点的历史条目是自动创建的,而不是由 pushState 以编程方式创建的吗? 但如果是这样,History API 将只对完整的单页应用程序有意义。

任何浏览器的行为都是相同的。希望你能帮助我:)

【问题讨论】:

  • Popstate 仅在 URL 更改但您仍在同一页面上时触发。因此,当您从 /books/harry-potter/ 按下返回按钮时,您只需加载 /search/ 并且不会触发 popstate 事件。因此,一种解决方法是:在 /search/ 的页面加载时,您将不得不读取 URL 并提取搜索查询。
  • 感谢您的回答,但是“仅当 URL 更改时”是什么意思? URL 一直在变化(从 / 到 /search,从 /search 到 /books 等)。
  • 假设您在 /search/{query2} 并按回... URL 将更改为 /search/{query1} 并且因为文档上下文仍然与来自 /search 的相同/{query1},触发 popstate 事件。相反,当您在 /books/harry-potter/ 并按回时,URL 将更改,整个文档将替换为 /search/{query2} - 不会触发 popstate 事件,因为它是不同的文档语境。如果用户在您的搜索页面上然后直接进入谷歌,然后按回...“返回”操作没有发生在您的网页上,因此 popstate 也不会发生
  • 啊,都是关于文档上下文的,谢谢!因此,正如我在问题中提到的,History API 确实只对单页应用程序有意义。我在网上找不到有关该(重要)点的任何信息。恰恰相反,德国的 mozilla 文档完全具有误导性:根据他们的说法,当您导航到像 google 这样的完整其他页面并返回时,会触发一个 popstate 事件。即使在原始的英文文档中,您也可以找到这一段,但至少被划掉了....developer.mozilla.org/en-US/docs/Web/API/…
  • @DarrylHuffman 但不幸的是,您的解决方法(从 URL 中提取查询)对我没有多大帮助,因为在来回导航时,javascript 不会在所有浏览器中可靠地调用。

标签: javascript browser-history html5-history


【解决方案1】:

对于想要更多解释为什么 popstate 事件仅在某些情况下发生的任何人,这对我有帮助:

MDN popstate event page 上写着:

每次活动历史条目在同一文档的两个历史条目之间发生变化时,都会向窗口调度一个 popstate 事件

只有在同一文档的两个历史记录条目之间导航时,才会触发 popstate 事件,例如单击后退按钮(或在 JavaScript 中调用 history.back()).

所以看起来只有在导航到同一文档中的不同 url 时才会调用 popstate。这适用于 SPA,但不适用于其他任何东西。

作为补充说明,html5 spec for session history 似乎并不清楚何时调用 popstate 事件:

在导航到会话历史条目时,在某些情况下会触发 popstate 事件。

这可能表明不同的浏览器会以不同的方式对待它。

我希望从其他人那里获得更多见解

【讨论】:

    猜你喜欢
    • 2015-03-19
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-12
    相关资源
    最近更新 更多