按钮事件中window.location更改时,IE9 onbeforeunload调用了两次..最小繁殖

IE9 onbeforeunload called twice when window.location changed in button event... minimal reproduction

本文关键字:两次 繁殖 调用 onbeforeunload location window 事件 IE9 按钮      更新时间:2023-09-26

我一直在努力,但却一无所获。

我有一个取消按钮,点击后会显示"window.location='404.htm';"。onbeforeunload处理程序会触发两次,但前提是用户在第一个对话框中单击"Stay on this page"。正常导航(页面刷新,转到主页)onbeforeunload处理程序只触发一次。

我已经设法用最少的HTML和脚本重新处理了这种行为:

<!DOCTYPE html>
<html>
<head>
    <title>Test page</title>
</head>
<body onbeforeunload="return 'Unsaved changes';">
    <form name="form1" id="form1">
        <input id='cmdCancel' type="button" value="Cancel" onclick="window.location = '404.htm';" />
    </form>
    <script type="text/javascript">
        /*
         * Connecting the events via code makes no difference
         *
        document.forms[0].cmdCancel.onclick =
            function () {
                alert('Clicked cancel. About to navigate...');
                window.location = '404.htm';
            };
        window.onbeforeunload = function () {
            return "Unsaved changes";
        }; 
        */   
    </script>
</body>
</html>

"onbeforeunload调用两次"有很多点击量,但没有最低限度的复制,也没有实际的解决方案。

有什么建议吗?

谢谢!

试试看,这对我很有效。这个解决方案最初由Amit发布在http://social.msdn.microsoft.com/Forums/eu/sharepointinfopath/thread/13000cd8-5c50-4260-a0d2-bc404764966d?prof=required

记住,暂时禁用onbeforeunload并在短时间后将其启用是关键。

var checkChangesEnabled = true;
window.onbeforeunload = confirmExit;
function confirmExit()
{
  if(checkChangesEnabled)
  {
    event.returnValue = "You have not saved your document yet.";
    disableCheck();
  }
}
function disableCheck()
{
  checkChangesEnabled = false;
  setTimeout("enableCheck()", "100");
}
function enableCheck()
{
   checkChangesEnabled = true;
}

不管怎样,onbeforeunload都是通过JS来解释的,您可能可以在全局变量中使用布尔标志来知道这是否是事件启动的进程第一次运行。类似:

<head>
  ...
  <script ...>
  var flag=true;
  var ret="";
  function getoff() {
    if(flag) {
      //do your things and save your return value to the global variable "ret"
      //ret="Unsaved changes";
      flag=false; //with this, the code above will be executed only once
    }
    return ret; //the second call will return the same thing as the first call, as first call's return value is stored in a global variable, and is not modified during the second call
  }
  </script>
</head>
<body onbeforeunload="return getoff();">
...

另一种可能是,根据这篇文章,问题似乎来自于使用JS更改页面,你可以使用隐藏的超链接来使用HTML更改页面,比如:

<a href="404.htm" id="myButton" style="display:none;visibility:hidden;"></a>

然后你的按钮可以做:

<input type="button" ... onclick="document.getElementById('myButton').click();">

假设这些都有效,像这样的隐藏链接就是一个丑陋的黑客攻击(第一种可能性无论如何都不漂亮),但当MSIE表现得像一个网络浏览器时,不需要一些丑陋的黑客。。。

使用下一个代码,您可以在任何情况下修复此问题:

window.location = 'javascript:window.location = "http://www.google.com"';

我发现当使用回发和非asp标记的控件时,它会被调用两次。将控件从<button>更改为<asp:Button>等以解决此问题。

我想我找到了一个更干净的解决方案。我在回调中将onbeforeunload设置为null,并在退出前重置它:

...
window.onbeforeunload=confirmExit;
function confirmExit(){
    window.onbeforeunload=null;
    event.returnValue="You have not saved your document yet.";
    window.onbeforeunload=confirmExit;
}