window.onbeforeunload可能会多次触发

仅仅因为你没有看到用于某个function并不意味着它没用。

Stack Exchange网络,GMail,Grooveshark,Yahoo! Mail和Hotmail使用onbeforeunload提示来防止/警告用户在开始编辑内容后离开页面。 哦,是的, 几乎每个接受可保存用户输入数据的桌面程序都使用这种提示用户离开前的UX模式。


我有一个与此类似的function:

window.onbeforeunload = function(){ // only prompt if the flag has been set... if(promptBeforeLeaving === true){ return "Are you sure you want to leave this page?"; } } 

当用户尝试离开页面时,浏览器会向他们显示离开或停留在页面上的选项。 如果用户选择“保留此页面选项”,然后在页面完全卸载之前再次快速单击链接,则会再次触发对话框。

这个问题有什么万无一失的解决方案吗?


注意:以下不是解决方案:

 var alreadyPrompted = false; window.onbeforeunload = function(){ // only prompt if the flag has been set... if(promptBeforeLeaving === true && alreadyPrompted === false){ alreadyPrompted = true; return "Are you sure you want to leave this page?"; } } 

因为用户可能会选择“留在页面上”选项,这将导致将来的onbeforeunload s停止工作。

我认为你可以通过在onbeforeunload回调中启动的计时器( setInterval )来实现这一点。 确认对话框启动时,Javascript执行将暂停,如果用户取消,则定时function可以将alreadyPrompted变量重置为false,并清除间隔。

只是一个想法。

好的,我根据你的评论进行了快速测试。

 0 window.onbeforeunload = function () { setInterval(function () { $('#counter').html(++counter); }, 1); return "are you sure?"; } window.onunload = function () { alert($('#counter').html()) }; 

在两个回调之间#counter永远不会高于2(ms)。 似乎将这两个回调结合使用可以满足您的需求。

编辑 – 回答评论:

关。 这就是我的想法

 var promptBeforeLeaving = true, alreadPrompted = false, timeoutID = 0, reset = function () { alreadPrompted = false; timeoutID = 0; }; window.onbeforeunload = function () { if (promptBeforeLeaving && !alreadPrompted) { alreadPrompted = true; timeoutID = setTimeout(reset, 100); return "Changes have been made to this page."; } }; window.onunload = function () { clearTimeout(timeoutID); }; 

我用一个易于使用的函数封装了上面的答案:

 function registerUnload(msg, onunloadFunc) { var alreadPrompted = false, timeoutID = 0, reset = function() { alreadPrompted = false; timeoutID = 0; }; if (msg || onunloadFunc) { // register window.onbeforeunload = function() { if (msg && !alreadPrompted) { alreadPrompted = true; timeoutID = setTimeout(reset, 100); return msg; } }; window.onunload = function() { clearTimeout(timeoutID); if (onunloadFunc) onunloadFunc(); }; } else { // unregister window.onbeforeunload = null; window.onunload = null; } } 

注册使用:

 registerUnload("Leaving page", function() { /* unload work */ }); 

要取消注册使用:

 registerUnload(); 

希望这可以帮助 ..