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

时间:2016-11-21 19:36:34

标签: javascript macos reactjs caching safari

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

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

在Safari上,但是:

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

什么是更奇怪:我可以看到我每次在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)的页面缓存不应成为问题的原因。

2 个答案:

答案 0 :(得分:3)

问题

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

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

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

解决方案

我发现只有一个有效的解决方案,但它有点不完美,黑客和丑陋。

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

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

重要提示:

  

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

     

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

所以,请按照自己的责任使用它:

window.onpageshow = function(event) {
    if (event.persisted) {
        window.location.reload();
    }
};

积分

答案 1 :(得分:1)

似乎是Safari的后退/转发缓存问题。此缓存(也称为BFCache或页面缓存)存储整个网页的当前状态,包括JavaScript代码状态,并在用户按浏览器的“后退”按钮时恢复它。你可以阅读它here。通常在加载的网页浏览器上使用beforeunload时,关闭BFCache。但是,您的JavaScript代码中可能存在阻止此行为的内容。或者你可能设置unSaved state = false然后它被缓存?尝试通过在页面上添加变通方法来手动关闭后退/前进缓存:

window.onpageshow = function(event) {
    if (event.persisted) {
        window.location.reload() 
    }
};