Ajax,后退按钮和DOM更新


113

如果javascript修改了页面A中的DOM,则用户导航到页面B,然后单击返回按钮以返回到页面A。对页面A的DOM的所有修改都将丢失,并且向用户显示最初从服务器检索到的版本。

它可以在stackoverflow,reddit和许多其他流行的网站上以这种方式工作。(尝试向该问题添加测试评论,然后导航至其他页面并单击“返回”按钮以返回-您的评论将“消失”)

这很有道理,但是某些网站(apple.com,basecamphq.com等)以某种方式迫使浏览器向用户提供页面的最新状态。(转到http://www.apple.com/ca/search/?q=ipod,单击顶部的“说下载”链接,然后单击“后退”按钮-所有DOM更新将被保留)

不一致来自何处?


有趣的是,苹果计算机在不修改哈希值的情况下记住了该状态。hmmm
James

苹果看起来好像他们只是在操纵响应缓存
BigBlondeViking

正如其他人已经暗示的那样,这与javascript或ajax无关。您应该删除这些标签以获得正确答案。
BYK

苹果公司的例子很差。如果您收缩搜索区域[ex:products],请单击您的链接,然后按返回,则不会保留DOM。您正在寻找许多建议的哈希解决方案。
BigBlondeViking

当我按下“后退”按钮时,Apple根本不记得我在搜索结果的哪一页。使用IE7。您需要一个哈希解决方案。请参阅:Facebook。
乔什·斯托多拉

Answers:


106

一个答案:除其他事项外,卸载事件会使后退/前进缓存无效

一些浏览器将整个网页的当前状态存储在所谓的“ bfcache”或“页面缓存”中。这样,他们可以在通过后退和前进按钮导航时非常快速地重新呈现页面,并保留DOM和所有JavaScript变量的状态。但是,当页面包含onunload事件时,这些事件可能会将页面置于非功能状态,因此该页面未存储在bfcache中,必须重新加载(但可以从标准缓存中加载)并重新从头开始渲染,包括运行所有onload处理程序。通过bfcache返回页面时,DOM保持其先前状态,而无需触发onload处理程序(因为该页面已被加载)。

请注意,关于Cache-Control和其他HTTP标头,bfcache的行为与标准浏览器缓存不同。在许多情况下,浏览器会将页面缓存在bfcache中,即使它不将其存储在标准缓存中也是如此。

jQuery会自动将卸载事件附加到窗口,因此不幸的是,使用jQuery会使您的页面无法保存在bfcache中以进行DOM保留和快速前进/后退。[更新:此问题已在jQuery 1.4中修复,因此仅适用于IE]


3
你完全钉了它。reddit和stackoverflow都在使用jquery,而basecamp和apple在使用prototype.js。这几乎说明了一切。
lubos hasko 09年

+1有趣(虽然不是跨浏览器),这个问题与它开始时的问题大不相同...
BigBlondeViking

1
它可能是跨浏览器的,因为我也可以在Internet Explorer上复制它。我敢肯定,每个启用了javascript的网络浏览器都必须处理此问题。但这确实是一团糟,当您考虑到这一点时,后退按钮应始终将人们带到他们最近一次看到的页面,其中包含所有DOM更新,javascript状态等。如果这样做的话,Web浏览器不应尝试根本不使用bfcache来解决问题。整个卸载事件是一个大笑话。我敢肯定,有99%的时间用于修补内存泄漏。
lubos hasko 09年

1
具体来说,IE内存泄漏。:) jQuery卸载事件也恰好修复了Firefox 2中的一个(完全不相关的)错误。但是对于其他浏览器来说则不必要。 dev.jquery.com/ticket/3015 我想我听说过onunload的其他用途,例如出站点击跟踪或保存webapp状态,但是我从来没有理由自己使用它,以及开发人员是否想使用它们网站对用户而言速度更慢,更痛苦(我讨厌导航回reddit评论页面如何重置评论折叠状态),这是他们的特权。
英里

1
卸载事件仅适用于IE,不适用于Firefox和chrome。Safari的最新版本可保留dom状态,而开发人员无需执行任何操作。
David

15

我一直在尝试使Chrome的行为像Safari一样,而我发现可行的唯一方法是Cache-control: no-store在标头中进行设置。当用户按下“后退”按钮时,这将迫使浏览器从服务器重新获取页面。这并不理想,但是比显示过时的页面更好。


5
这是对原始问题的正确答案。如果要强制在后退按钮上重新加载服务器,请使用缓存控制“不存储,不缓存,必须重新验证”。Chrome要求不设商店,而IE要求必须重新验证。对于其他浏览器(和w3c),没有缓存就足够了。
woens

3

Facebook通过修改ajax请求的URL中的哈希标识符来记住页面状态。这些更改会记录在浏览器的历史记录中,因此,当用户单击“后退”按钮时,哈希将更改为以前的样子。因此,这意味着您将需要一些Java脚本来监视has标识符并在浏览器更改它时做出反应。 Andreas Blixt有一个可用的哈希监视脚本


截至今天为止,它并没有做不到,所以可以告诉我Facebook现在在做什么
Ravinder Payal


2

在依赖Ajax和DOM更新的Web应用程序中,使用URL哈希/片段标识符是挂钩/记住状态的一种很常见的方法。

查看“ 真正简单的历史”项目,了解一些想法。可以监视URL的哈希值更改,而rsh会考虑浏览器的差异来做到这一点。


1

对于任何遇到Rails此问题的人-您的问题不是bfcache(我认为是)-就是turbolinks宝石。是如何删除它。

希望这可以节省您一些时间,让您的头撞在墙上。


0

您正在寻找某种类型的URL哈希管理。网址中的#仅用于客户端。

当您使用JS更改背面的状态时,您将更新网址#中的数据。

此外,您还会添加某种类型的轮询,以监视哈希是否已更改,并根据哈希中的新数据加载页面的状态。

看看这个:

http://ajaxpatterns.org/Unique_URLs


3
这与哈希符号无关。
卡·马太斯

3
您错了,他正在寻找最常用的方法来保留AJAX解决方案中的页面状态。
BigBlondeViking
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.