拦截页面退出事件

IT技术 javascript internet-explorer dom-events
2021-01-26 08:19:59

在我的系统中编辑页面时,用户可能决定导航到另一个网站,这样做可能会丢失他们尚未保存的所有编辑。

我想拦截任何转到另一个页面的尝试,并提示用户确保他们希望发生这种情况,因为他们可能会丢失当前的工作。

Gmail 以非常相似的方式执行此操作。例如,撰写一封新电子邮件,开始在邮件正文中输入内容并在地址栏中输入新位置(例如 twitter.com 或其他内容)。它会提示询问“你确定吗?”

想法如何复制这个?我的目标是 IE8,但也希望与 Firefox 和 Chrome 兼容。

4个回答

类似于 Ghommey 的回答,但这也支持旧版本的 IE 和 Firefox。

window.onbeforeunload = function (e) {
  var message = "Your confirmation message goes here.",
  e = e || window.event;
  // For IE and Firefox
  if (e) {
    e.returnValue = message;
  }

  // For Safari
  return message;
};
@mtmurdock,第二个语句“ var e = e || window.event;” 意味着设置e等于参数e(如果它是真的)或 window.event 如果不是真的。如果参数e为空,则不为真
2021-03-13 08:19:59
在 Chrome 中不再工作(已弃用):developers.google.com/web/updates/2016/04/...
2021-03-17 08:19:59
IE8 不支持 @Blieque addEventListener。不要在没有阅读问题的情况下编辑人们的答案。
2021-03-23 08:19:59
你能解释一下第一行吗(var message = ...)?我不知道那个逗号和第二个表达式在做什么。
2021-04-01 08:19:59
@mtmurdock 这只是用于声明多个变量的 Javascript 语法。 var foo, bar;是相同的var foo; var bar;
2021-04-02 08:19:59

看到这篇文章。您正在寻找的功能是onbeforeunload

示例代码:

  <script language="JavaScript">
  window.onbeforeunload = confirmExit;
  function confirmExit()
  {
    return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
  }
</script>
有什么方法可以确定用户选择了“离开此页面”选项而不是“留在此页面上”?
2021-03-21 08:19:59
@ShilpaSoni 你很快就会得到一个后续的卸载事件developer.mozilla.org/en-US/docs/Web/API/Window/unload_event但我认为没有同步的方式。
2021-03-22 08:19:59

除了烦人的确认弹出窗口之外,最好延迟一点(几毫秒)来管理成功地将未保存的数据发布到服务器,我使用将虚拟文本写入控制台来管理我的站点,如下所示:

window.onbeforeunload=function(e){
  // only take action (iterate) if my SCHEDULED_REQUEST object contains data        
  for (var key in SCHEDULED_REQUEST){   
    postRequest(SCHEDULED_REQUEST); // post and empty SCHEDULED_REQUEST object
    for (var i=0;i<1000;i++){
      // do something unnoticable but time consuming like writing a lot to console
      console.log('buying some time to finish saving data'); 
    };
    break;
  };
}; // no return string --> user will leave as normal but data is send to server

编辑: 另请参阅Synchronous_AJAX以及如何使用jquery执行此操作

这正是它起作用的原因:确实在计算暂停之前发送了post-request,但是在实际离开之前对页面的这种小阻塞确保了浏览器客户端(不是javascript)有足够的时间真正正确地完成发送这个请求. 我注意到当我只发送请求(没有阻塞)并立即离开页面时,请求并不总是发送。
2021-03-17 08:19:59
这完全没有意义-1。javascript 没有线程你正在做的是做一个 postRequest 然后暂停站点的计算,不允许任何人做任何事情(包括你的 postRequest,同时在计算暂停之前已经发送了)。
2021-03-25 08:19:59
@fmsf 神圣的语法!!
2021-03-26 08:19:59
我喜欢这个弹出窗口的替代方案。谢谢你的建议,雷米。
2021-03-27 08:19:59
我不会在生产中使用它。console.log 不是跨浏览器;每个 postRequest 都会受到前一个 postRequest 的延迟(这也意味着页面将在循环期间挂在那里 * 预定请求);请求不是并行启动的;你不能保证真的发送你的请求。如果我被迫面对这个问题,如果只有一个请求,我会使用同步 ajax 请求。对于多个请求,我会使用异步 ajax 请求和一个循环来检查请求回调的结果(成功或错误)。
2021-04-09 08:19:59

我有用户没有完成所有必需的数据。

<cfset unloadCheck=0>//a ColdFusion precheck in my page generation to see if unload check is needed
var erMsg="";
$(document).ready(function(){
<cfif q.myData eq "">
    <cfset unloadCheck=1>
    $("#myInput").change(function(){
        verify(); //function elsewhere that checks all fields and populates erMsg with error messages for any fail(s)
        if(erMsg=="") window.onbeforeunload = null; //all OK so let them pass
        else window.onbeforeunload = confirmExit(); //borrowed from Jantimon above;
    });
});
<cfif unloadCheck><!--- if any are outstanding, set the error message and the unload alert --->
    verify();
    window.onbeforeunload = confirmExit;
    function confirmExit() {return "Data is incomplete for this Case:"+erMsg;}
</cfif>