【发布时间】:2014-07-28 14:27:45
【问题描述】:
这个问题可能听起来很奇怪,因为大多数情况下 popstate 是在用户按下后退按钮时同步触发的。
然而,W3C 规范规定,当traversing history(参见第 14 项)时,UA(浏览器)可以对 popstate 进行排队,即。 popstate 被异步触发(即使此时 URL 已更改)。
浏览器供应商以不同方式解释和实施此规范。 Mozilla decides Firefox 应该能够在 load 之前触发 popstate,并且有充分的理由,这样慢速图像就不会阻塞 popstate。
Chrome/Safari 另有决定,这导致了我们的问题:
在管理 Web 应用的历史记录时,通常希望尽快启动历史记录管理,例如。在DOMContentLoaded 而不是load。 但作为回报,用户无法退出任何pushState,因为所有popstate 都在排队等待load。
我们正在寻求有关处理此类情况的方法的建议。我自己想出了一些:
- 延迟加载图片,所以
load可以尽快触发。 - 在
load被触发之前阻止用户界面。 - 在
load而不是DOMContentLoaded上初始化框架。
有更好的解决方案吗?
更新:当有 ajax 在load 之前触发时,事情会变得很糟糕,如果这些请求导致 DOM 更改,并且 DOM 更改恰好有一些图像,load 会延迟到那些图片已加载/超时,这意味着popstate 的排队时间更长。
更新 2:要为其添加一个简单的演示,请使用 chrome 访问此 jsbin page 并查看 popstate 将被阻止,直到 load 被触发。您可以比较缓存图像和未缓存图像的结果。
【问题讨论】:
-
使用后退按钮时
popstate应始终立即触发。唯一不会触发的情况是您刷新时,但在这种情况下,您最好以 URI 为基础(这就是刷新的重点)。我一定错过了什么,但不确定是什么。 -
@DavidMulder 我已经添加了一个 jsbin 页面来演示这个问题。
-
啊,至少我现在知道你在
load发生之前触发了历史状态更改......你到底为什么要这样做?只有用户应该更改状态,并且应用程序第一次加载后退按钮不应该有任何以前的应用程序特定状态,所以我完全混淆了你想要做什么。 -
@DavidMulder 我们非常努力地不这样做。但是由于 3G 网络不稳定,我们看到很多用户遇到了图像仍在加载的问题(因此 onload 没有触发),但是 js 框架已经启动(因为 dom 已准备好)。因为我们用js处理历史,当用户点击一个链接时,pushstate被触发,而onload此时还没有触发,所以当用户点击返回按钮时,我们无法通过监听popstate来处理它。
-
您正在构建单状态应用程序吗?如果是这样,我认为在初始化时阻止 UI 一次是合理的。每个页面都会发送一个设置脚本,该脚本会初始化然后解析原始 url 请求。用户在您的应用启动时会经历稍长的加载时间,但应该为以后的请求加快速度。
标签: javascript html browser-history