转载:http://www.w3help.org/zh-cn/causes/BX2047

标准参考

无。

问题描述

一般情况下,onbeforeunload 事件处理函数内会写入一些提示性语句,当用户的浏览器跳转到其他页面时,用来提醒用户当前页面将要跳转,请用户决定是否观看新页面。
或者在 onbeforeunload 事件内处理一些业务逻辑,在浏览器跳转到新页面之前 ,执行一些业务逻辑,如保存用户浏览信息等。

简单的说这个事件应仅在页面 URL 发生变化时触发,但是在 IE 中 使用 JavaScript 伪协议执行脚本程序时,也会触发 onbeforeunload 事件。

造成的影响

此问题不会造成大问题,但会导致不友好的提示出现,稍微影响用户操作体验。

受影响的浏览器

所有浏览器  

问题分析

onbeforeunload 事件是非 W3C DOM-Event 标准事件,它属于 BOM (Browser Object Model) 范畴。到现在为止 BOM 还没有被标准化,它由各个浏览器厂商制定,因此会有实现差异。

时至今日,HTML5 规范草案中已经开始标准化 BOM,遗憾的是 onbeforeunload 事件的触发条件还没有在草案中作出详细说明。

更多内容可参考:6.1.6.2 Event handlers on elements, Document objects, and Window objects

最初的 onbeforeunload 事件支持是由 IE4.0 版本提供,存在于 BODY、FRAMESET 的 DOM 对象及 window 对象之中,随后被其他浏览器复制,但具体事件触发方式并没有统一。

根据 MSDN 中描述,IE 的 onbeforeunload 事件可由以下这些条件触发:

  • 关闭当前浏览器窗口。
  • 导航到另一个进入一个新的地址或选择一个喜欢的位置。
  • 单击后退,前进,刷新,或主页按钮。
  • 点击一个链接到新页面。
  • 调用 超链接的 click 方法。
  • 调用 document.write 方法。
  • 调用 document.open 方法。
  • 调用 document.close 方法。
  • 调用 window.close 方法。
  • 调用 window.open 方法,窗口名称设置值为 _self。
  • 调用 window.navigate 或 NavigateAndFind 方法。
  • 调用 location.replace 方法。
  • 调用 location.reload 方法。
  • 指定一个 location.href 属性的新值。
  • 使用 submit 按键提交表单,或调用 form.submit 方法。

更详细的说明可以查考 MSDN 原文:onbeforeunload Event

在这些触发条件中绝大多数都使页面产生了跳转,但还缺少一些常见情况说明,即页面 URL 可能发生了变化但没有产生跳转。比如 "javascipt:" "mailto:" 等常见的浏览器内置伪协议,以及由第三方或用户自定义的为协议时,页面并不跳转,而是根据伪协议执行指定的行为。这个情况应加入到触发条件中。

根据以上所有这些触发条件,我们构建如下代码来检测各浏览器对 onbeforeunload 事件的支持程度与触发条件:

<script>
window.onbeforeunload=function(){
  return "请点击取消留在此页";
}
</script>
请手工关闭当前浏览器窗口。<br/>
请手工单击后退,前进,刷新,或主页按钮。<br/>
请手工在地址栏输入其他页面地址或从收藏夹、历史记录中将页面导航其他站点。<br/>
<a href="http://www.google.com" id="A">点击一个链接到新页面</a><br />
<button onclick="document.getElementById('A').click()">调用 anchor.click 方法</button><br />
<button onclick="document.write('A')">调用 document.write 方法</button><br />
<button onclick="document.open()">调用 document.open 方法</button><br />
<button onclick="document.close()">调用 document.close 方法。</button><br />
<button onclick="window.open('http://www.google.com','_self')">调用 window.open方法,窗口名称设置值为 _self。</button><br />
<button onclick="try{window.navigate('http://www.google.com')}catch(e){alert('不支持此方法')}">调用 window.navigate 方法</button><br />
<button onclick="try{window.external.NavigateAndFind('http://www.google.com','','')}catch(e){alert('不支持此方法')}">调用 NavigateAndFind 方法</button><br />
<button onclick="location.replace('http://www.google.com')">调用 location.replace 方法</button><br />
<button onclick="location.reload()">调用 location.reload 方法</button><br />
<button onclick="location.href='http://www.google.com'">指定一个 location.href 属性的新值</button><br />
<form action="http://www.google.com" id="B">
<input type="submit" value="提交具有action属性的一个表单">
</form>
<button onclick="document.getElementById('B').submit()">调用 form.submit 方法</button>
<a href="javascript:">调用 javascipt: 伪协议</a><br />
<a href="mailto:"&gt;调用&nbsp;mailto:&nbsp;伪协议&lt;/a&gt;&lt;br&nbsp;/&gt;<br />&lt;a&nbsp;href="custom:">调用自定义伪协议</a>

执行结果汇总入表:

  IE Firefox Chrome Safari Opera
关闭当前浏览器窗口 事件被触发 事件被触发 事件被触发 不支持该事件
导航到另一个进入一个新的地址或选择一个喜欢的位置 事件被触发 事件被触发 事件被触发 不支持该事件
单击后退,前进,刷新,或主页按钮 事件被触发 事件被触发 事件被触发 不支持该事件
点击一个链接到新页面 事件被触发 事件被触发 事件被触发 不支持该事件
调用 anchor.click方法 事件被触发 不支持此方法1 不支持此方法1 不支持该事件
调用 document.write方法 事件被触发 事件被触发 事件未触发 不支持该事件
调用 document.open方法 事件被触发 事件被触发 事件未触发 不支持该事件
调用 document.close方法 事件未触发 事件未触发 事件未触发 不支持该事件
调用 window.open方法,窗口名称设置值为 _self 事件被触发 事件被触发 事件被触发 不支持该事件
调用 window.navigate 事件被触发 不支持此方法2 不支持此方法2 不支持该事件
调用 NavigateAndFind方法 事件被触发 不支持此方法3 不支持此方法3 不支持此方法3
调用 location.replace 方法 事件被触发 事件被触发 事件被触发 不支持该事件
调用 location.reload 方法 事件被触发 事件被触发 事件被触发 不支持该事件
指定一个 location.href 属性的新值 事件被触发 事件被触发 事件被触发 不支持该事件
使用 submit 按键提交表单 事件被触发 事件被触发 事件被触发 不支持该事件
调用 form.submit 方法 事件被触发 事件被触发 事件被触发 不支持该事件
调用 javascipt: 伪协议 事件被触发 事件未触发 事件未触发 不支持该事件
调用 mailto: 伪协议 事件未触发 事件未触发 事件被触发 不支持该事件
调用自定义伪协议 事件被触发 事件被触发 事件被触发 不支持该事件

注 1: 直接调用链接元素的 click 方法模拟鼠标点击事件,只有 IE 和 Opera 支持,BX9052: IE Opera 支持使用 window.navigate 方法控制页面跳转 和 SD9025: IE6 IE7 IE8 Opera 支持除 INPUT 和 BUTTON 元素以外的其他元素的 'click' 方法。 
注 2: 使用 window.navigate 方法导航网页仅被 IE Opera 支持,可参考 MSDN 原文:navigate Method。 
注 3: NavigateAndFind 方法处于 window.external 对象中,external 对象也仅 IE 支持,可参考 MSDN 原文:NavigateAndFind Method 和本站文章 BT9012: IE 的 external 对象提供的方法是 IE 特有的

结合汇总表可以看出:

  • Opera 并不支持 onbeforeunload 事件。
  • Chrome Safari 在调用 document.write、document.open、document.close 方法以及 "javascipt:" 伪协议时,不会触发 onbeforeunload 事件。
  • Firefox 在调用 document.close 方法和 "javascipt:"、"mailto:" 伪协议时,不会触发 onbeforeunload 事件。
  • IE 浏览器在调用 document.close 方法和 "mailto:" 伪协议时,不会触发 onbeforeunload 事件。

解决方案

onbeforeunload 事件还未标准化,各浏览器的支持以及事件触发条件差异较多,需谨慎使用。

如必须在非 Opera 浏览器内使用该事件,应尽量避免在页面中调用常见的 "javascrpt:" 以及其他伪协议,以此回避不同浏览器中 onbeforeunload 事件被频繁触发。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.10
Chrome 7.0.544.0 dev
Safari 5.0.2
Opera 10.62
测试页面: onbeforeunload_event_differences.html
本文更新时间: 2010-10-13

关键字

javascipt URL Protocol onbeforeunload

各浏览器对 onbeforeunload 事件的支持与触发条件实现有差异的更多相关文章

  1. 10、网页制作Dreamweaver(扩展:各浏览器对 onunload 事件的支持与触发条件实现有差异)

    标准参考 在 HTML 4.01 规范中关于 onunload 事件的描述是:当 document 从 window 中移除时,触发 onunload 事件. 关于 HTML 4.01 规范中 onu ...

  2. 关于windows phone 8.1系统手机对html5触摸事件的支持情况

    近日购入一部微软Lumia 640手机,目的主要就是为了测试年中开发完成的响应式移动web项目,同时也为了将来升级win10 mobile系统.由于我们的项目目前只考虑支持IOS与Android系统, ...

  3. onunload与onbeforeunload事件解析 标签: 浏览器 2017-04-10 09:46 45人阅读 评论(0)

    注:只测试了chrome和IE浏览器的表现情况 onunload事件 //JS Document window.onunload = onunload_message; function onunlo ...

  4. JS事件 卸载事件 当用户退出页面时(页面关闭、页面刷新等),触发onUnload事件,同时执行被调用的程序。注意:不同浏览器对onunload事件支持不同。

    卸载事件(onunload) 当用户退出页面时(页面关闭.页面刷新等),触发onUnload事件,同时执行被调用的程序. 注意:不同浏览器对onunload事件支持不同. 如下代码,当退出页面时,弹出 ...

  5. JS之onunload、onbeforeunload事件详解

    简介 onunload,onbeforeunload都是在刷新或关闭时调用,可以在<script>脚本中通过 window.onunload来调用.区别在于onbeforeunload在o ...

  6. 160503、onunload、onbeforeunload事件详解

    最近项目中做到一个功能:在上传页面用户开始上传文件之后用户点击任意跳转都需要弹出提示层进行二次确定才允许他进行跳转,这样做的目的是为了防止用户的错误操作导致这珍贵的UGC 流失(通常用户在一次上传不成 ...

  7. onunload、onbeforeunload事件详解--zhuan

    最近项目中做到一个功能:在上传页面用户开始上传文件之后用户点击任意跳转都需要弹出提示层进行二次确定才允许他进行跳转,这样做的目的是为了防止用户的错误操作导致这珍贵的UGC 流失(通常用户在一次上传不成 ...

  8. Spring中ApplicationContext对事件的支持

    Spring中ApplicationContext对事件的支持   ApplicationContext具有发布事件的能力.这是因为该接口继承了ApplicationEventPublisher接口. ...

  9. Javascript检测浏览器对CSS属性的支持 /* supports */

    //检测浏览器对CSS属性的支持 supports = (function() { var div = document.createElement('div'), vendors = 'Khtml ...

随机推荐

  1. Color the Fence

    Codeforces Round #202 (Div. 2) B:http://codeforces.com/problemset/problem/349/B 题意:给你一些颜料,然后你可以用这些颜料 ...

  2. STM8S 模拟I2C程序

    STM8S的硬件I2C还是存在问题,不敢贸然使用. 于是决定用模拟I2C. #define SCL PE_ODR_ODR1 #define SDA PE_ODR_ODR2 #define SDAM P ...

  3. bcb6 中安装 delphi7 的控件包

    其实只要新建一个包,然后把 d7 中的包包含的 pas 文件也包含进去就行了. 同时它会把对应的 bpi 文件也自动包含. 对于 bcb6 中没有的 PosEx 函数可以这样处理,把 d7 中的实现复 ...

  4. ArrayList的toArray

    ArrayList提供了一个将List转为数组的一个非常方便的方法toArray.toArray有两个重载的方法: 1.list.toArray(); 2.list.toArray(T[]  a); ...

  5. org.springframework.beans.BeanUtils

    org.springframework.beans.BeanUtils的一个demo.可以很优雅的实现将父类字段的值copy到子类中 下面例子的输出结果(子类使用父类的toString方法,有点意思吧 ...

  6. 【面试&笔试】ASP.NET的相关问题

    1.      介绍ASP.NET 答:ASP.NET不是一种语言,而是创建动态web页的一种强大的服务器端技术,它是Microsoft.NETFramework中一套用于生成Web应用程序和Web服 ...

  7. Oracle预估的基数算法

    SQL> create table t as select * from dba_objects; Table created. SQL> create index idx_t on t( ...

  8. Tribles(概率)

    Description   Problem ATribblesInput: Standard Input Output: Standard Output GRAVITATION, n."Th ...

  9. bzoj3043

    这道题完全没想出来,引自 http://blog.csdn.net/willinglive/article/details/38419573的题解 对于带有“将一段区间内的每个数全部加上某个值”这种操 ...

  10. Android USB安全调试

    Android 4.2.2 引入了USB安全调试方面的内容,当启用安全调试的时候,只有被用户认证过的主机才可以通过Android SDK自带的ADB工具经由USB连接来访问设备的内部构件. 下面以an ...