如何阻止windows.onbeforeunload被IE中的javascript:href链接触发?

时间:2011-10-04 15:10:12

标签: javascript jquery internet-explorer onbeforeunload onunload

我正在为我的表单构建一个故障保护,它会警告用户,如果他们离开页面,他们的表单数据将会丢失(类似于gmail所做的)。

window.onbeforeunload = function () {    
        if (formIsDirty) {
            return "You have unsaved data on this form. Don't leave!";
        }
}

以上功能在firefox中运行良好,但在IE中它由任何href链接触发,即使是链接到javascript而不是其他页面的链接。

例如......

<a href='javascript:someFunction();'>click</a>

我想知道是否有办法解决这个问题,因为我不希望用户认为他们只是点击它上面的按钮就离开了页面。 我没有选择重写所有各种链接,因为它们内置且数量众多。

有什么想法吗?

6 个答案:

答案 0 :(得分:35)

您可以在悬停这些链接时删除并重新分配onbeforeunload:

jQuery(
  function($)
  {
      //store onbeforeunload for later use
    $(window).data('beforeunload',window.onbeforeunload);  

      //remove||re-assign onbeforeunload on hover 
    $('a[href^="javascript:"]')
      .hover( 
             function(){window.onbeforeunload=null;},
             function(){window.onbeforeunload=$(window).data('beforeunload');}
            );

  }
);

答案 1 :(得分:7)

我遇到了类似的问题并找到了一个非常简单的解决方案:

$("a").mousedown(function() {
    $(window).unbind();
});

这将在触发click事件之前删除onbeforeunload事件。

答案 2 :(得分:3)

将任何脚本移动到click事件处理程序,并为没有JavaScript的用户提供后备页面:

<a href="foo.html" onclick="someFunction(); return false">click</a>

不引人注目的JS支持者可能会反对使用onclick属性,但事实是它有效,这是添加事件处理程序的最简单方法,也是提供示例的最简单方法。为了更好地分离关注点,您可以改为使用DOM0 onclick属性,addEventListener() / attachEvent()或库。

答案 3 :(得分:1)

如果您在a标签的href中包含书签符号,那么您应该仍然可以使用onclick事件来包含JavaScript。

<a href="#" onclick='someFunction();'>click</a>

我已经运行了许多测试,这似乎是在不触发onb​​eforeunload事件的情况下执行JavaScript。我很想知道这是否适用于其他人,或者在以这种方式实施标签后仍然存在同样的问题。

答案 4 :(得分:1)

(像其他一些答案一样,这需要改变JavaScript的绑定方式。如果这对你不起作用,请忽略。)

我发现在IE 7到IE 10中,简单地使用带有preventDefault的jQuery .click()工作而不显示onbeforeunload消息(IE 11没有显示beforeunload消息我的任何测试用例)。无论href是'#'还是javascript:void(0),都是如此。如果直接使用attachEvent / addEventListener,我希望结论成立,但我没有对此进行测试。

http://jsbin.com/tatufehe/1有以下演示。两个版本(绿色)preventDefault都有效(不显示beforeunload对话框)。没有preventDefault的那个确实显示了它(作为比较)。


$( document ).ready( function () {
  $( 'a' ).click( function ( evt ) {
    $( '#display' ).text( 'You clicked: ' + $( this ).text() );

    if ( $(this).hasClass( 'withPreventDefault' ) ) {
      evt.preventDefault();
    }
  } );
})

window.onbeforeunload = function () {
  return "Are you sure you want to leave?";   
};

<p id="display"></p>

<p><a class="withPreventDefault" href="#">Number sign link *with* preventDefault</a></p>

<p><a class="withPreventDefault" href="javascript:void(0);">JavaScript href link *with* preventDefault</a></p>

<p><a href="javascript:void(0);">JavaScript href link *without* preventDefault</a></p>

答案 5 :(得分:0)

如果用户鼠标位于链接上,并且他们使用键盘触发刷新页面或激活键盘链接,则提示将不会显示。因此Dr.Molle方法在这种罕见的情况下不起作用。