HTML5 History API:从另一个页面导航回来时不会调用“popstate”

jar*_*ccc 2 javascript browser-history html5-history

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

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

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

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

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

然后我的点击流是:

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

  1. 当我走了回去通过点击浏览器的后退按钮,我会希望与根据状态对象触发了“popstate”事件。但什么也没有发生。-路径更改为 /search

  1. 当我再回去一次时,我收到一条警告,其中popstate: null -路径更改为 /

  2. 当我在那之后继续前进时,我得到popstate: {"q":"harry potter"} -路径更改为 /search


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

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

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

dho*_*ton 6

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

MDN popstate 事件页面上,它指出:

每次活动历史条目在同一文档的两个历史条目之间更改时,都会向窗口分派 popstate 事件。

在同一文档的两个历史条目之间导航时,popstate 事件仅通过执行浏览器操作触发,例如单击后退按钮(或在 JavaScript 中调用 history.back())。

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

作为附加说明,会话历史记录html5 规范似乎并不清楚何时调用 popstate 事件:

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

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

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