一:文档
window.onload | document.onDOMContentLoaded | |
---|---|---|
描述 | 当一个资源及其依赖资源已完成加载时,将触发load事件 | 当初始HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,无需等待样式表,图像和子框架的完成加载 |
常规-规范 | DOM L3 | HTML5 |
常规-接口 | UIEvent | Event |
常规-是否冒泡 | 否 | 是 |
常规-能否被取消 | 否 | 能(尽管一个简单的事件被指定为不可取消) |
目标 | window | document |
默认行为 | 无 | 无 |
属性 | target,type,bubbles,cancelable,view,detail | target,type,bubbles,cancelable |
二、何时触发这两个事件?
1、当 onload 事件触发时,页面上所有的DOM,样式表,脚本,图片,flash都已经加载完成了。
2、当 DOMContentLoaded 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash。
三、为什么要区分?
开发中我们经常需要给一些元素的事件绑定处理函数。但问题是,如果那个元素还没有加载到页面上,但是绑定事件已经执行完了,是没有效果的。这两个事件大致就是用来避免这样一种情况,将绑定的函数放在这两个事件的回调中,保证能在页面的某些元素加载完毕之后再绑定事件的函数。
当然DOMContentLoaded机制更加合理,因为我们可以容忍图片,flash延迟加载,却不可以容忍看见内容后页面不可交互。、
这里又要牵扯到页面加载渲染的原理了:
1、加载样式表会阻塞外链脚本的执行
一些Gecko和Webkit引擎版本的浏览器,包括IE8在内,会同时发起多个Http请求来并行下在样式表和脚本。但脚本不会被执行,直到样式被加载完成。在未加载完之前甚至页面也不会被渲染。但是在opera中样式的加载不会阻塞脚本的执行。
因此:目前通用的作法是把脚本和样式都以外链形式引入,甚至在jquery的官方文档中也是这样推荐的。对于大部分脚本来说,这样的脚本等待外链的机制还是有意义的,比如一些DOM和样式操作需要读取元素的位置,颜色等。这就需要样式先于脚本加载
2、各大javascript框架如何实现domReady事件的
早期版本的浏览器是没有DOMContentLoaded事件的那么它们怎么模拟实现类似功能呢?先来说说原理
(1)、如果是webkit引擎则轮询document的readyState属性,当值为loaded或者complete时则触发DOMContentLoaded事件,对webkit525之后版本直接可以注册DOMContentLoaded事件
if(Browser.Engine.webkit){
timer = window.setInterval(function(){
if(/loaded|complete/.test(document.readyState))
fireContentLoadedEvent();
},0);
}
(2)、IE处理方式有多种a、在页面临时插入一个script元素,并设置defer属性,最后把该脚本加载完成视作DOMContentLoaded事件来触发。这样做有一个问题是,如果插入脚本的页面包含iframe的话,会等到iframe加载完才触发,其实这与onload是无异的。即这个方法不准确。
b、通过setTiemout来不断的调用documentElement的doScroll方法,直到调用成功则出触发DOMContentLoaded。这样做的原理是在IE下,DOM的某些方法只有在DOM解析完成后才可以调用,doScroll就是这样一个方法,反过来当能调用doScroll的时候即是DOM解析完成之时,与prototype中的document.write相比,该方案可以解决页面有iframe时失效的问题
c、首先注册document的onreadystatechange事件,但经测试后该方法与window.onload相当,效果不大。下面是jquery做的兼容性处理代码。
document.attachEvent("onreadystatechange",
function(){
if( document.readyState ==="complete"){
document.detachEvent("onreadystatechange", arguments.callee );
jQuery.ready();}
});