转载: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. 生成mif文件的几种方法总结

    mif文件就是存储器初始化文件,即memory initialization file,用来配置RAM或ROM中的数据.生成QuartusII11.0可用的mif文件,有如下几种方式: 方法1:利用Q ...

  2. 【VB】操作ODBC-DAO方式操作只能查询,不能更新插入操作解决。

    最近接手一个改善项目,需要从Access转化到SQL Server 2014,使用原有的ODBC连接方式只能查询,不能更新插入.网上一直找不到解决方案,然后自己测试一下使用ADO方式竟然可以连接了.具 ...

  3. Google为何这么屌

    概述: 在移动市场上,从来没有一个公司像Google一样的玩法,以后可能也不会有.因为这根本就不是一个商业模式.它可以调动极大的资源而几乎没有盈利压力,它力逾千钧又身段灵活.它从来不尊重这个市场原有的 ...

  4. MiniProfiler.3.0.10 用于MVC4.0中不能显示SQL语句

    MiniProfiler.3.0.10 用于MVC4.0中可以显示执行时间,但是不能显示SQL语句,怎么解决?

  5. 以Facebook为案例剖析科技公司应有的工具文化

    http://www.36kr.com/p/146507.html 编者按:本文由 @王淮Harry哥 撰写,摘自他即将出版的新书.王淮是 Facebook 早期员工,中国藉第二位工程师第一位研发经理 ...

  6. rsync使用说明

    需求:把10.5.128.190数据同步到10.5.128.27 用客服端-服务器模式,需要从客户端发起 也就是从10.5.128.27发起 10.5.128.27 作为客户端 10.5.128.19 ...

  7. C# Linq-Aggregate

    The easiest to understand definition of Aggregate is that it performs an operation on each element o ...

  8. HDU4681 String(dp)

    题目链接. #include <iostream> #include <cstdio> #include <cstring> #include <cstdli ...

  9. Javascript面向对象编程(二):构造函数的继承 by 阮一峰

    今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...

  10. Light OJ 1027 - A Dangerous Maze(概率)

    题目大意: 你在一个迷宫里,你面前有n个门,你选择门的概率是一样的,每扇门有一个数字k, 加入这个数字是负数,那么这个门会花费你abs(k)分钟后把你带回原点, 假如这个数字是正数,他可以把你带出迷宫 ...