`

各浏览器对页面 onload 事件处理方式不一致

阅读更多
问题描述
页面加载完成后会触发 onload 事件,通常下会使用 window.onload 、 document.body.onload、 HTMLIFrame.onload 方法来处理他;但是各浏览器对页面 onload 事件处理方式并不一致,这些方法可能会导致页面加载完成后无法触事件处理函数。

造成的影响
window.onload 与 document.body.onload 事件相互关系不明确。

IE6 IE7 IE8 中无法通过为属性赋值方式为 IFRAME 元素绑定 load 事件处理函数。

受影响的浏览器
IE6 IE7 IE8 Firefox 

问题分析
一、window.onload 与 document.body.onload 事件以及 BODY 标签内的内联 onload 事件,三者相互关系不明确
有关这两个事件在 W3C 指定的规范中并没有说明其区别,由于 window 对象属于 BOM 范畴没有统一规范可依,各浏览器对其在此处的实现存有差异。

在微软的 MSDN 中说明 document.body.onload 属性是 window 的 onload 事件处理程序。其它浏览器厂商并没有对此属性做更细致解释。

分析以下代码:

<button onclick="alert(document.body.onload);">查看本页 document.body.onload 事件</button>
<button onclick="alert(window.onload);">查看本页 window.onload 事件</button>
<button onclick="alert(window.onload===document.body.onload);">查看document.body.onload 事件与 window.onload 事件是否为同一事件</button>
<br />
<script>
document.body.onload = function (){ // 函数 A
document.getElementById("A").innerHTML = "document.body.onload 被触发";
}
window.onload = function (){ // 函数 B
document.getElementById("B").innerHTML = "window.onload 被触发";
}
</script>
<span id="A" style="background:gold"></span>
<span id="B" style="background:gray"></span>
代码中分别对两种 onload 属性赋值了不同的事件处理函数。其中 window.onload 先于 document.body.onload 被定义。如果他们两者使用的是同一事件处理源,则会发生 window 对象中 onload 事件定义被 body 的事件处理函数所覆盖。

实际上个浏览器运行结果如下:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
实际运行 window.onload 被触发
document.body.onload 事件函数 函数 B 函数 A 函数 B
window.onload 事件函数 null 函数 B
两者事件处理函数是否一致 Flase Flase true

初步可以看出:

在 IE 中 window.onload 事件函数即使定义了,也会是 null ,它的事件处理函数始终是为 document.body.onload 提供的;
在 Firefox 中 document.body.onload 事件不与 window.onload 事件相同,后者事件函数不会覆盖前者;
在 Chrome Safari Opera 中 document.body.onload 事件处理函数被后声明的 window.onload 事件处理函数覆盖。
为了更明确以上猜测,我们将两个事件处理函数位置对调后再来观察实际效果:

window.onload = function () // 函数 B{
document.getElementById("B").innerHTML = "window.onload 被触发";
}

document.body.onload = function (){ // 函数 A
document.getElementById("A").innerHTML = "document.body.onload 被触发";
}
这次试图使用 document.body.onload 事件处理函数来覆盖 window.onload,实际运行结果如下:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
实际运行 document.body.onload 被触发 window.onload .onload 被触发 document.body.onload 被触发
document.body.onload 事件函数 函数 A 函数 A 函数 A
window.onload 事件函数 null 函数 B
两者事件处理函数是否一致 Flase Flase true

可以看出:

无论如何在 IE 中 window.onload 事件函数即使定义了,也会是 null ,它的事件处理函数始终是为 document.body.onload 提供的。
在 Firefox 中 只有 window.onload 事件会触发页面加载完成事件,document.body.onload 只是个由用户扩展的方法,并不触发相应事件处理函数。这也说明了为什么仅在 Firefox 浏览器中,两者"事件"函数均被保留。
在 Chrome Safari Opera 中页面加载完成事件由 document.body.onload 和 window.onload 两者的事件处理函数定义顺序有关,后定义的覆盖之前定义的,两者最终会使用同一事件源函数处理事件内容。
在实际应用中 onload 事件还可能被写在 BODY 标签的属性内,而不在脚本标签中定义他的处理函数。此时代码如下:

<script>
window.onload=function(){
alert("window onload");
}
</script>
<body onload="alert('overridden window onload')">
此用例中首先在脚本标签内为 window.onload 事件附加了处理函数,然后有在 BODY 标签内写入 onload 事件处理代码。如果 BODY 标签内的 onload 事件处理与 window.onload 事件处理不同,就会弹出两次对话框,并且可以根据对话框出现的顺序判断哪个 onload 事件处理在前。反之则只会弹出一个对话框,如果仅出现 "window onload" 字样提示就说明 BODY 标签内 onload 属性无效,如果出现 “overridden window onload” 提示就说明 BODY 标签内 onload 事件与 window.onload 事件为同一事件处理机制,后者覆盖了前者。

各浏览器运行结果如下:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
实际运行 ”overridden window onload“
两者均代表 window onload 事件 true

可见,在所有浏览器中均将,BODY 标签内的内联 onload 事件处理等同与 window.onload 事件处理。

结合上文说明可知, Firefox 中 BODY 标签内的 onload 事件属性与脚本标记内写入的 document.body.onload 事件并不一致。



二、IE6 IE7 IE8 中无法通过为属性赋值方式为 IFRAME 元素绑定 load 事件处理函数
某些情况下可能需要为 IFRAME 标记动态添加 onload 监听事件,其实现方法有通常有三种:

直接为 HTMLIFrameElement.onload 属性为 IFRAME 标记赋值事件处理函数
使用 HTMLIFrameElement.setAttribute 方法为 IFRAME 标记赋值事件处理函数
使用事件监听方式为 IFRAME 的 onload 事件绑定处理函数
根据 DOM 规范推荐使用第三种处理方式,但是由于规范在不断修正添加中,浏览器开发时可能相应的标准规范并未出现或者并不完善,这导致了各个版本浏览对此问题的实现差异。

以下将依次分析这三种方式在各浏览器内的处理情况。



1.直接为 HTMLIFrameElement.onload 属性为 IFRAME 标记赋值事件处理函数

分析以下代码:

<body>
<div id="msgA">通过 HTMLIFrameElement.onload 属性动态加入事件处理函数的 IFRAME 没有触发 onload 事件。</div>
<div id="msgB">静态 IFRAME 没有触发 onload 事件。</div>
<br />
<script>

function iframeLoadA(){
document.getElementById("msgA").innerHTML = "通过 HTMLIFrameElement.onload 属性动态加入事件处理函数的 IFRAME 已经触发 onload 事件。";
}
function iframeLoadB(){
document.getElementById("msgB").innerHTML = "静态 IFRAME 已经触发 onload 事件。";
}

window.onload = function (){
var iframeB = document.getElementById("ifarmeB");
var iframeA = document.createElement('iframe');
iframeA.onload = iframeLoadA;
document.body.appendChild(iframeA);
}

</script>
<iframe id="ifarmeB" onload="iframeLoadB()"></iframe>
</body>
页面中存在两个 IFRAME 标记,ifrmaeA 标记为动态生成,并且动态为其 onload 属性赋值了加载完成后的处理函数。而 iframeB 标记则是在页面中静态存在的,其 onload 属性对应的事件处理函数已经被固定写入。

运行此代码,在各个浏览器中效果如下:

  IE6 IE7 IE8 Firefox Chrome Safari Opera
HTMLIFrameElement.onload = Function  没有触发 onload 事件 触发 onload 事件
静态 onload 属性定义 触发 onload 事件

可见,在 IE 浏览器中通过 HTMLIFrameElement.onload 属性赋值方式无法响应 IFRAME 标记的 onload 事件。而其他浏览器均支持此写法。



2.使用 HTMLIFrameElement.setAttribute 方法为 IFRAME 标记赋值事件处理函数

将以上代码稍作修改,将 HTMLIFrameElement.onload 赋值语句部分修改为 HTMLIFrameElement.setAttribute方法:

window.onload = function (){
var iframeB = document.getElementById("ifarmeB");
var iframeA = document.createElement('iframe');
iframeA.setAttribute("onload","iframeLoadA()");
document.body.appendChild(iframeA);
}
此时 ifrmaeA 标记的 onload 属性以及事件处理函数被 DOM 标准方法 setAttribute 写入。

运行此代码,在各个浏览器中效果如下:

  IE6 IE7 IE8(Q) IE8(S) Firefox Chrome Safari Opera
HTMLIFrameElement.setAttribute 没有触发 onload 事件 触发 onload 事件
静态 onload 属性定义 触发 onload 事件

可见,在 IE 系列浏览器中仅有 IE8(S) 支持通过 setAttribute 方法为 IFRAME 标记写入 onload 属性以及其事件处理函数。而其他浏览器均支持此写法。



3.使用事件监听方式为 IFRAME 的 onload 事件绑定处理函数

再将以上代码稍作修改,使用 DOM 规范中推荐的事件监听绑定方法为 IFRAME 动态加入 onload 事件处理函数:

function addEvent(eventName,element,fn){
if (element.attachEvent) element.attachEvent("on"+eventName,fn);
else element.addEventListener(eventName,fn,false);
}
window.onload = function (){
var iframeB = document.getElementById("ifarmeB");
var iframeA = document.createElement('iframe');
addEvent("load",iframeA,iframeLoadA);
document.body.appendChild(iframeA);
}
代码中为了兼容 IE 私有的事件绑定方式,封装了名为 addEvent 的处理函数,他为 IE 和其他浏览器提供不同的事件绑定方法,以达到兼容效果。

运行此代码,在各个浏览器中效果如下:

  IE6 IE7 IE8(Q) IE8(S) Firefox Chrome Safari Opera
onload 事件监听绑定 触发 onload 事件
静态 onload 属性定义

此时所有浏览器中为 IFRAME 标记动态绑定的 onload 事件处理方法均生效。



综合以上三种常见情况可以得出结论,除 IE 以外的浏览器均支持对以上三种动态定义 onload 事件处理函数的方法,而所有 IE 系列浏览器对 HTMLIFrameElement.onload 属性的赋值不被支持,他们可以通过 DOM 标准方法 setAttribute 来为 HTMLIFrameElement 类型元素设置 onload 属性,但是由于 IE8 以下版本对 setAttribute 方法支持有限,导致仅 IE8(S) 下生效。最终 IE 浏览器只能通过事件监听方式为 HTMLIFrameElement 类型元素绑定 onload 事件处理函数。



解决方案
统一为 window 对象的 onload 事件绑定函数,避免在 Firefox 中产生 document.body.onload 事件理解歧义。
统一使用 DOM 规范的事件监听方法(或 IE 专有事件绑定方法)为 IFRAME 标记绑定 onload 事件处理函数。
分享到:
评论

相关推荐

    各浏览器对link标签onload/onreadystatechange事件支持的差异分析

    然而,不同的浏览器对这两个事件的支持情况存在差异,这可能会导致在不同浏览器上的表现不一致。下面将详细介绍这两个事件以及它们在各主流浏览器中的行为。 1. **onload事件**: - 在IE6、IE7、IE8和IE9,以及...

    鼠标事件大全 包括不同浏览器是否支持 鼠标事件非常完整

    ### 鼠标事件大全与跨浏览器兼容性详解 在Web开发中,了解并掌握...在实际开发中,应考虑目标用户的浏览器分布,优先使用广泛支持的事件,同时为不支持的浏览器提供降级方案或替代策略,以实现最佳的跨浏览器兼容性。

    浏览器兼容页面开发注意事项(javascript篇)_101028参考.pdf

    不同的浏览器可能对某些API、事件处理或DOM操作有不同的实现,这可能导致代码在某些浏览器上运行正常而在其他浏览器上出现问题。以下是一些主要的浏览器兼容性问题及解决策略: 1. `document.form.item` 问题:在旧...

    网页页面加载动画(含有HTML字符实体+CSS动画animation+js事件onbeforeunload、onload).zip

    而`onload`事件则在页面所有资源(包括图片、脚本等)完全加载完毕后触发,此时可以关闭加载动画,显示完整的页面内容。 在这个项目中,有两个不同的加载效果,可能一个是基于HTML字符实体的简单滚动动画,另一个...

    多浏览器事件[总结].pdf

    在软件开发领域,尤其是Web开发,理解不同浏览器对JavaScript事件的支持至关重要。事件是JavaScript与用户交互的核心机制,它们允许我们监听并响应用户的操作,如点击、滚动或输入等。以下是对给定文件中多浏览器...

    javascript 多浏览器 事件大全

    总结来说,通过了解和运用这些JavaScript多浏览器事件大全中的事件,开发者能够构建更为丰富和响应迅速的网页应用,同时确保在不同浏览器和平台上提供一致的用户体验。掌握这些知识对于前端开发人员来说是必不可少的...

    一些主流JS框架中DOMReady事件的实现小结

    综上,我们可以看出,尽管各主流JavaScript框架对DOMReady事件的具体实现各有差异,但它们的核心目标都是一致的:允许开发者在DOM树构建完成后尽早执行JavaScript代码,而不必等待所有其他资源加载完成。这样做的...

    IE中图片的onload事件无效问题和解决方法

    此外,如果需要在所有浏览器中保持一致的行为,还可以考虑使用`window.onload`或`document.DOMContentLoaded`事件来确保在所有图片加载完毕后再执行后续操作。但请注意,这些全局事件可能会影响整个页面的加载时机,...

    页面中body onload 和 [removed] 冲突的问题的解决

    这种方法可以减少事件监听器的数量,提高性能,但不适用于本场景中处理页面加载事件。 4. **使用 `DOMContentLoaded` 事件**: 如果你只需要在DOM加载完成后执行操作,而不关心外部资源,可以使用 `...

    JavaScript事件处理

    - **特点**:提供了更一致和强大的事件处理机制,支持事件捕获和冒泡。 - **优势**:能够更好地处理复杂的事件流,支持多个事件监听器。 #### 三、HTML文档事件 ##### 1. 浏览器事件 - **定义**:指浏览器自身...

    同时兼容IE和FireFox的事件处理event代码--添加文件上传例子

    在这些早期浏览器中,事件处理的实现方式有所不同,导致开发者需要编写特定的代码来确保功能的一致性。 首先,我们需要理解`event`对象在不同浏览器中的处理方式。在标准的DOM事件模型中,`event`对象作为参数传递...

    浏览器兼容总结.txt

    IE 和 Firefox 在处理页面加载事件时也有所不同。在 IE 中,可以使用`document.body.onload=inject;`来指定页面加载完成后的回调函数;而在 Firefox 中,需要使用`document.body.onload=inject();`。为了解决这一...

    刷新导致页面字体变大的解决方法

    4. **动态调整字体大小**:在JavaScript中,可以使用`window.onload`或`$(document).ready()`函数来监听页面加载完成事件,然后根据实际需要动态调整字体大小,确保无论何时刷新页面,字体大小都能保持一致。...

    css3处理所有浏览器都兼容的无图片圆角问题

    在网页设计中,圆角效果经常被用于提升页面的视觉美观度,但早期的CSS标准并未提供原生支持,导致在不同浏览器间实现圆角效果存在兼容性问题。随着CSS3的推出,这个问题得到了很好的解决。本文将详细介绍如何使用CSS...

    无线Web页面事件机制调研

    在事件支持方面,XHTML MP规定浏览器必须支持onload和onclick事件,其他如onchange、onfocus等为可选支持,具体支持情况会因不同的浏览器实现而异。 无线Web页面事件机制在WAP 2.0和XHTML MP的框架下,成为了开发者...

    vue h5移动端禁止缩放代码

    在移动浏览器中,默认情况下,用户可以通过双指开合来缩放页面,这对于提高用户体验有一定的帮助。但有些场景下,开发者可能出于设计需求,希望禁止这种缩放行为,比如保证特定元素的显示大小或防止布局错乱等。针对...

    iframe的onload在Chrome/Opera中执行两次Bug的解决方法

    这可能是由于Safari 5对`iframe`加载的处理方式与其他浏览器不同,或者可能是由于网络延迟、资源加载问题或者是浏览器自身的兼容性问题。对于这种情况,开发者可能需要进一步调试和测试,以找出问题的根源并进行优化...

    Vue监听页面刷新和关闭功能

    此外,在页面关闭或刷新时,事件触发的顺序是:先触发`onbeforeunload`事件,然后是`onunload`事件,最后执行`onload`事件。需要注意的是,在`onunload`事件中进行的操作,用户体验可能不会很好,因为该事件触发时...

    实现浏览器全屏窗口的几种方法

    - 修改`&lt;body&gt;`标签,添加相应的事件监听器,如`onLoad`用于在页面加载完成后自动执行全屏操作。 - 示例代码如下: ```html &lt;title&gt;123 ;charset=gb2312"&gt; function omiga_window() { window.open(...

Global site tag (gtag.js) - Google Analytics