*onbeforeunload* 是否缓存在 Safari (macOS) 上?

jua*_*cks 3 javascript safari macos caching reactjs

beforeunload 按照惯例在我的 JS/ReactJS 应用程序中添加了一个事件列表。该函数根据内部unSaved状态添加确认对话框。

在 Chrome 和 Firefox(macOS/桌面)上一切正常。

然而,在 Safari 上:

  • 第一次“我使用”事件处理程序(我离开页面时unSaved==true),它按预期工作正常,
  • 然而,在随后尝试使用 离开页面时unSaved==true,Safari 根本不要求任何确认。
  • 当我转到一个新选项卡(具有相同的先前 URL)时,第一次再次有效,随后的时间则不...

更奇怪的是:我可以看到我添加的事件函数实际上每次在 safari 上都被调用,因为console.log每次确实都在打印测试。

我唯一可能的猜测是 Safari 以某种方式缓存了我对该选项卡的确认响应?(?)

关于如何解决这个问题的任何想法?

我的堆栈:

Safari: Version 10.0.1 (12602.2.14.0.7) macOS: 10.12.1 (16B2657) host: localhost protocols: tested on both, http and https

更多信息:

  • 事件pageshow的属性persisted始终设置为 false。因此,Safari 的页面缓存 (BFCache) 不应该是问题的原因。

Kal*_*sev 5

问题

您的问题是由称为后向缓存 (BFCache)的浏览器功能引起的。

当用户导航离开时,它应该保存页面的完整状态。这个想法是当用户使用后退按钮向后导航时,可以非常快速地从缓存中加载页面。

Chrome 和 Firefox 将事件上的事件处理程序beforeunload视为不在向后缓存中存储页面的信号,但 Safari 忽略此类处理程序。


解决方案

我只找到了 1 个可行的解决方案,但它有点不完美、笨拙和丑陋。

您可以检查onpageshow事件的持久属性。它在初始页面加载时设置为 false。当页面从back-forward cache它加载时设置为true.

onpageshow事件与事件类似onload,不同之处在于它发生在onload页面首次加载时的事件之后。此外,onpageshow每次加载页面时都会发生该事件,而onload从缓存加载页面时不会发生该事件。

需要注意的重要事项:

该解决方案相当不完美,因为页面在重新加载之前仍会短暂显示。这意味着,您的页面正在加载...然后 - 它被迫重新开始。毕竟,它不像在页面完全加载后触发重新加载,但仍然如此。

还有一件小事:当然,通过禁用javascript可以轻松绕过解决方案。

因此,请自行负责使用它:

window.onpageshow = function(event) {
    if (event.persisted) {
        window.location.reload();
    }
};
Run Code Online (Sandbox Code Playgroud)

学分