我在我的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)的页面缓存不应成为问题的原因。答案 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()
}
};