如何将AJAXy页面更新与"后退"按钮混合,以便在用户返回时仍然存在更新?

Rom*_*kov 7 html browser ajax back-button

我有一个用户可以修改的页面.所有修改都使用JQuery执行,并且还发送到服务器,因此完全重新加载也将生成修改后的页面.

这在Windows上的Firefox 11/Chrome中工作正常:即使用户导航到其他地方然后使用"后退"按钮,他们也会获得包含最新编辑的页面.

但是,如果我现在将Google地图嵌入到页面中,则"后退"按钮将停止工作:它会将用户带到页面之前的所有编辑状态.除了在浏览器的缓存中,此页面甚至不再存在,但它仍会显示.

我在这里放了一个简单的测试用例 显示这种行为.

是什么赋予了?我怎样才能解决这个问题?完美的解决方案只允许浏览器返回而不重新加载页面,就像它通常会做的那样.

PS显然,"工作"示例实际上并不适用于OSX上的Chrome.我如何解决浏览器坚持回到页面陈旧版本的问题?

描述此行为的错误报告:Firefox


赏金:Windows上的Firefox和Chrome 表现出两种行为(在一种情况下返回修改后的DOM,但在另一种情况下不再修改).是否有描述浏览器该做什么的规范?是否存在以这种或那种方式改变的错误?这个问题有一个我可以google的通用名称吗?

我正在考虑一个解决方案,我通过JavaScript更新隐藏元素,然后检查更新是否仍然存在.如果是这样,"后退"按钮恢复了最新的DOM,并且不需要做任何其他事情.如果没有,浏览器恢复过时的DOM,我可以强制重新加载页面,就像那样令人不快.对这种方法的任何评论也是受欢迎的.

注意:真实网站有比这更可编辑的控件,其中一个是自由格式文本区域.即使用户刚刚添加了几段文本,我也希望提议的解决方案能够正常工作.例如,这种东西不能附加到URL之后#.

Nic*_*lay 5

将Google地图嵌入到页面中会禁用bfcache(我将使用mozilla术语缺少标准术语),因为在a中加载的地图页面<iframe>使用了一个unload侦听器.

MDN上列出了在Firefox中快速返回导航页面未被缓存的可能原因:使用Firefox 1.5缓存.您的问题被列为"顶级页面包含不可缓存的帧",这令人困惑,我将在稍后澄清.(其他浏览器可能使用类似的启发式方法,因为这些规则是为避免破坏现有内容而开发的 - 另请参阅此答案,它有一些链接.)

解决这个问题的正确方法是与Google的某个人交朋友,然后唠叨他们,直到他们onunload至少从地图的嵌入页面中移除听众.

通常,您不应该依赖bfcache工作或不为特定页面工作.这只是对常见情况的优化.由于它是优化,因此可以禁用它,例如当系统内存不足时.如果用户在返回之前重新启动浏览器,或者关闭选项卡并选择"撤消关闭选项卡",它也将无效,如您在错误中所述.

您应该从JS恢复页面状态或将页面标记为不可缓存(使用HTTP标头).当然,前者可以带来更好的用户体验.@Adam Gent的建议看起来是正确的,我将不得不检查他引用的Firefox问题.


bfcache以这种方式工作的原因是:

  • 如果浏览器运行onunload处理程序,然后通过bfcache恢复页面,页面可能会被破坏,因为脚本经常删除onunload处理程序中的事件侦听器("清理",除了旧的IE版本之外,这不是必需的)
  • 如果浏览器停止onunload在页面中运行处理程序,因为用户可能会返回页面而他们想要缓存它,作者会抱怨.
  • 如果iframe中的页面无法缓存,则恢复缓存的外部页面并重新加载内部页面有时会破坏它们(例如,如果两个页面都是同一个域,则外部页面可以保存对框架中对象的引用,这会赢得重新加载内部框架后无效.因此,如果没有缓存iframe,则父页面也不会.

当您点击"返回"时页面仍然从(磁盘)缓存加载的原因是,您可能已指定可以缓存发送到浏览器的内容.浏览器无法知道您更改服务器上的页面并对其进行DOM更改.

希望这可以帮助.


[edit]我将详细说明上面的"将页面标记为不可缓存"的想法.要使Web浏览器缓存为您而不是对您起作用,重要的是要记住HTTP是用于检索资源的协议.例如,URL http://bbb.akshell.com/broken标识的HTML页面是一种资源.当您通过HTTP提供资源时,您可以指定浏览器的资源副本有效期(即匹配服务器上资源的规范版本).

当您的测试用例中的资源是HTML页面,其中用户选择的项目以特殊方式标记时,资源可能随时更改(每次用户更改选择时).这意味着在提供此资源时的诚实HTTP响应将是"不缓存,可能随时更改".然后,浏览器每次需要加载页面时都会从服务器重新加载页面 - 正确的行为,但代价是用户的速度慢.

另一种适用于在多个页内标签之间切换的方法是将每个选择与其自己的URL相关联.具有两个选项卡的页面将对应于两个资源(和两个URL) - 每个选项卡一个.两种资源都可以由浏览器缓存(HTTP-).更改URL和页面内容可以在没有通过pushState到服务器的往返的情况下实现.

另一种方法似乎更适用于您的情况,您可以在其中保存用户在服务器上的输入:将应用UI和用户数据分离到不同的资源(即带有JS的静态(HTTP)可缓存HTML页面,加载用户来自单独的不可缓存URL的数据).请求用户数据并在加载时更新UI.[/ edit]