我在 beforeunload
上添加了一个事件列表 as customary在我的 JS/ReactJS 应用程序中。该函数根据内部 unSaved
状态添加确认对话框。
在 Chrome 和 Firefox(macOS/桌面)上一切正常。
然而,在 Safari 上:
- 第一次“我使用”事件处理程序(我在
unSaved==true
时离开页面),它按预期工作正常, - 然而,在随后使用
unSaved==true
离开页面的尝试中,Safari 根本不要求任何确认。 - 当我转到一个新选项卡(具有与之前相同的 URL)时,第一次仍然有效,但随后的时间不...
奇怪的是:我可以看到我添加的事件函数实际上每次都在 safari 上被调用,因为测试 console.log
确实每次都被打印出来。
我唯一可能的猜测是 Safari 以某种方式缓存了我对选项卡的确认响应? (?)
关于如何解决这个问题有什么想法吗?
我的堆栈:
Safari:版本 10.0.1 (12602.2.14.0.7)
macOS:10.12.1 (16B2657)
主机:本地主机
协议(protocol):在 http 和 https 上测试
更多信息:
- 事件
pageshow
的属性persisted
始终设置为 false。因此,Safari 的页面缓存 (BFCache) 不应是问题的原因。
最佳答案
问题
您的问题是由称为前后缓存 (BFCache) 的浏览器功能引起的。
它应该在用户导航离开时保存页面的完整状态。这个想法是当用户使用后退按钮导航回来时,可以非常快速地从缓存中加载页面。
Chrome 和 Firefox 将 beforeunload
事件上的事件处理程序视为不将页面存储在来回缓存中的信号,但 Safari 忽略此类处理程序。
解决方案
我只找到了 1 个可行的解决方案,但它有点不完美、粗糙且丑陋。
您可以检查 onpageshow
事件的持久属性。它在初始页面加载时设置为 false。当页面从 back-forward 缓存
加载时,它被设置为 true
。
onpageshow
事件类似于onload
事件,只是它在页面首次加载时发生在onload
事件之后。此外,每次加载页面时都会发生 onpageshow
事件,而从缓存中加载页面时不会发生 onload
事件。
重要提示:
The solution is rather imperfect as the page is still shown briefly before reloading. This means, your page loads... and then - it's forced to start all over again. After all, it's not like it's triggering a reload after the page is fully loaded, but still.
And one more minor thing: of course, the solution is easily bypassed by disabling javascript.
因此,请自行负责使用它:
window.onpageshow = function(event) {
if (event.persisted) {
window.location.reload();
}
};
致谢
- 关于 Safari Page Cache 的信息和 possible future changes to how unload events work
- Mika Tuupola 的 answer关于这个question
关于javascript - *onbeforeunload* 是否缓存在 Safari (macOS) 上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40727989/