如何在IE中防止javascript:href链接触发window.onbeforeunload?

28

我正在为我的表单构建一个故障保护机制,它会警告用户如果他们离开页面,他们的表单数据将会丢失(类似于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>

我想知道是否有办法解决这个问题,因为我不希望用户认为他们正在离开页面,而实际上只是单击页面上的按钮。由于链接已经内置且数量众多,我没有重写所有各种链接的选项。 有任何想法吗?

4
不要使用这样的链接,改用不显眼的JavaScript替代。 - SLaks
这不是一个选项。我们正在使用一个高度复杂的系统,它已经内置了所有这些东西。在这种情况下,我宁愿不要重新发明轮子。 - Maxx
页面加载后,你可以更改链接吗? - Tim Down
“不要离开!”这种用语很专制。你最好警告用户:“如果您离开,未保存的数据将会丢失。”如果用户想离开,无论你怎么劝阻,他们都会离开。你越是采取威逼手段,浏览器和用户就越会忽略它们。 - Nicolas Barbulesco
6个回答

37

当鼠标悬停在这些链接上时,您可以删除并重新分配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
我最终选择了这个解决方案。它按预期工作,并且对于这种解决方法来说相当稳定。感谢您的帮助。 - Maxx
这个很好用。然而,你也可以在绑定到锚点标签的函数中简单地返回false - 至少这是我能够解决这个问题的方法。 - anAgent
仅仅返回false在IE浏览器上似乎不起作用。我不得不采用使用onhover技巧的方法。 - shrisha
IE是魔鬼!除非政府强制要求我使用,否则我只会使用Chrome/Firefox。在使用IE方面的少数“好处”似乎并不有助于提高生产力。 - Hardryv
这个答案很有趣,但不够清晰。什么是“jQuery”?什么是单独的“$”? - Nicolas Barbulesco
显示剩余2条评论

8
我刚遇到了一个类似的问题,找到了一个非常简单的解决方案:
$("a").mousedown(function() {
    $(window).unbind();
});

在点击事件触发之前,这将删除onbeforeunload事件。


注意,此版本将适用于所有链接。 - Matthew Flaschen

3
将任何脚本移动到click事件处理程序中,对于没有JavaScript的用户使用回退页面:
<a href="foo.html" onclick="someFunction(); return false">click</a>

可能有些注重JS代码简洁的人会反对使用onclick属性,但事实是它可行,是添加事件处理程序和提供示例的最简单方式。为了更好的关注点分离,你可以使用DOM0的onclick属性、addEventListener() / attachEvent()或者一个库。


1
这仍会触发 onbeforeunload 事件。而且,我没有重写链接的时间。 - Maxx
谢谢您的更新,但这并不能阻止 onbeforeunload 事件的触发。 - Maxx
@Maxx: 只要someFunction()没有抛出错误,它不会触发beforeunload事件:return false就能确保这一点。 - Tim Down

1
如果你在a标签的href中包含书签符号,你仍然可以使用onclick事件来包含你的JavaScript。
<a href="#" onclick='someFunction();'>click</a>

我进行了多次测试,似乎可以在不触发onbeforeunload事件的情况下执行JavaScript。我很想知道这是否适用于其他人,或者在以这种方式实现标记后您是否仍然遇到同样的问题。


我相信这仍会触发调用,不幸的是。 - Maxx
我有一个“提交”按钮,所以我不能这样做。 - Nicolas Barbulesco
对我来说没问题,修复得很好,而且简单。 - aggaton

1
(与其他答案一样,这需要更改JavaScript的绑定方式。如果这对您不起作用,请忽略。)
我发现在IE 7到IE 10中,只需使用jQuery .click()和preventDefault,就可以避免显示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>

0
如果用户的鼠标在链接上,然后他们使用键盘刷新页面或者使用键盘激活链接,那么提示框将不会出现。因此,Dr.Molle的方法在这种罕见情况下无法奏效。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接