Ajax、后退按钮和 DOM 更新

IT技术 javascript ajax firefox
2021-01-21 07:23:19

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

它在 stackoverflow、reddit 和许多其他流行网站上都是这样工作的。(尝试向这个问题添加测试评论,然后导航到不同的页面并点击返回按钮返回 - 您的评论将“消失”)

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

不一致来自哪里?

6个回答

一个答案:除其他外,卸载事件会导致后退/前进缓存失效

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

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

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

具体来说,IE 内存泄漏。:) jQuery unload 事件也恰好修复了 Firefox 2 中的一个(完全不相关的)错误。但对于其他浏览器来说是不必要的。 dev.jquery.com/ticket/3015 我想我听说过 onunload 的其他用途,比如出站点击跟踪或保存 webapp 状态,但我从来没有理由自己使用它,如果开发人员想让他们的网站对他们的用户来说更慢,更痛苦(我讨厌导航回 reddit 评论页面如何重置评论折叠状态),这是他们的特权。
2021-03-26 07:23:19
+1 有趣(虽然不是跨浏览器)这个问题与开始时有很大不同......
2021-03-27 07:23:19
它可能是跨浏览器的,因为我也可以在 Internet Explorer 上重现它。我确信每个启用了 javascript 的网络浏览器无论如何都必须处理这个问题。但这真的是一团糟,当你想到这一点时,后退按钮应该总是让人们回到他们最后看到的页面,所有 DOM 更新,javascript 状态等。开发人员不应该通过在 unload 事件中做一些事情来破坏这一点,如果他们这样做,webbrowsers 不应该尝试通过不使用 bfcache 来解决问题。整个卸载事件就是一个大笑话。我确信 99% 的时间它都用于修补内存泄漏。
2021-04-01 07:23:19
你完全搞定了。reddit 和 stackoverflow 都使用 jquery,而 basecamp 和 apple 使用prototypejs。这几乎解释了一切。
2021-04-10 07:23:19
卸载事件仅适用于 IE,不适用于 Firefox 和 chrome。最新版本的 safari 保留了 dom 状态,而无需开发人员做任何事情。
2021-04-10 07:23:19

我一直在尝试让 Chrome 表现得像 Safari 一样,我发现可行的唯一方法是Cache-control: no-store在标题中进行设置当用户按下后退按钮时,这会强制浏览器从服务器重新获取页面。不理想,但比显示过时的页面要好。

这是原始问题的正确答案。如果您想在后退按钮上强制重新加载服务器,请使用缓存控制“no-store, no-cache, must-revalidate”。Chrome 需要 no-store,而 IE 需要 must-revalidate。对于其他浏览器(和 w3c),无缓存就足够了。
2021-03-31 07:23:19

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

截至今天,它还没有这样做,所以可以告诉我 facebook 现在做什么
2021-03-31 07:23:19

这与哈希 (#) 符号无关。

如果您要检查苹果的 HTTP 标头,它只是缓存页面。

苹果的例子很糟糕,他们没有“保存”页面状态,他假设 DOM 被保存是错误的
2021-03-29 07:23:19

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

查看真正简单的历史项目以获得一些想法。可以监视 URL 的哈希更改,而 rsh 会这样做,同时考虑到浏览器的差异。