2016-11-21 106 views
2

我在我的JS/ReactJS应用程序中添加了一个beforeunloadas customary事件列表器。该功能根据内部状态unSaved添加确认对话框。* onbeforeunload *缓存在Safari(macOS)上?

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

在Safari浏览器,但是:

  • 第一次“我使用”的事件处理程序(我离开,而unSaved==true页),它工作正常的aspected,
  • 然而,在随后的尝试离开页面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

由于关闭标签之前的“确认”在恶意网站上很常见,您可能会遭遇反恶意软件防护。 – ssube

+0

@ssube你的意思是Safari将我重复的确认尝试解释为恶意软件行为,因此只是忽略了我的逻辑? - Chrome和Firefox添加到确认弹出复选框,以供用户决定_“防止此页面创建额外的对话”_,这当然是非常明智的。 - Safari不提供这样的选项吗? – juanmirocks

+0

我不确定Safari的行为,但听起来像一个类似的功能可能会破坏你的代码。如果你曾经看到过一个页面反复打开对话框来阻止用户离开,大多数浏览器都有一些防范措施。如果Chrome和FF做得很好,那么Safari很可能会做一些阴暗和不幸的事情。 – ssube

回答

1

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

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

非常感谢@Sergey。您的答案和额外提供的解决方案可能会解决我的问题!我稍后再报告。 – juanmirocks

+0

非常感谢您。不幸的是,这并没有解决我的问题。请参阅:http://stackoverflow.com/questions/40727989/is-onbeforeunload-cached-on-safari-macos#comment69049563_40896361 - 你有任何其他想法?谢谢:) – juanmirocks

2

问题

你的问题是由浏览器的功能引起的称为背向前缓存(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(); 
    } 
}; 

现金

+0

非常感谢@卡洛扬。我会在今天晚些时候尝试解决方案并报告。并可能给你的赏金:-) – juanmirocks

+1

谢谢@ juanmirocks,我明白:-) –

+0

非常感谢你。你的回答非常清楚,非常丰富(为你带来赏金!)。 **非常不幸**,在尝试提出的解决方案后,我仍然体验到与Safari相同的以前的行为。我测试了'http'和'https'。更多信息,事件'pageshow'总是将'persisted'属性设置为'false'。事实上,我根本不使用后退/前进按钮。相反,我在具有普通页面链接的页面之间导航。所以我不知道...... ---真的很感激,如果你能想出其他假设:) – juanmirocks