从jQuery源码阅读看 dom load
最近两天不忙的时候再回过来研究一下jquery的源码,看到$(document).ready()时,深入的研究了一下dom的加载问题。
我们都知道,window.onload可以解决我们的js执行时机问题。有了它,可以把代码放在页面的任何位置。但是我们也知道,window.onload 要在html、css、js、img全部加载完后才会触发,而这样会影响页面的访问速度。因此,jquery通过封装$(function)做到了DOM加载完毕时就对js内容进行触发。
那jquery做到的原理是什么呢?我从原理上简单的做一下分析。
在IE9+、chorme、firefox等现代浏览器中,有个原生的js事件:DOMContentLoaded 当这个事件触发时,就说明DOM已经加载完毕,可以进行下面的js操作了
document.addEventListener('DOMContentLoaded',function(){alert(123);},false);
但是IE8以下是不支持这个事件的,所以IE用的是onreadystatechange事件
document.onreadystatechange = function(){
if(document.readyState == 'complete'){
alert('Dom已经加载完毕')
}
}
但是,非标准浏览器不会这么容易让我们好过。
首先,当document.readyState == 'complete'时,图片等文件已经加载完成了,虽然会在window.onload 之前执行,但是对交互效果来说还是触发的太晚了。有些站点的图片要下载下来是很慢很慢滴!
我在这里随便举个例子:
<body>
<div>12345555555555555555555555555</div>
<img src="http://b.hiphotos.baidu.com/zhidao/pic/item/c8177f3e6709c93da9f2dafa9b3df8dcd10054bf.jpg" alt=""> <script> alert(111)
window.onload = function(){
alert(456)
}
document.onreadystatechange = function(){
if(document.readyState == 'complete'){
alert(123);
//complete是指所有资源包括图片js等文件全部加载完成后才会触发。
//readyState == 'complete'确实会在onload前触发,但是还是触发的太晚。
}
} </script>
</body>
大家看,在IE8下,当页面执行时,首先弹出111,这毫无疑问。然后呢?对不起,是图片在页面中完全显示出来。然后再弹出123,最后弹出456.
再次,alert(123)执行时机也不确定,因为同一段代码,再IE7中,或者更高层的IE9种,有时图片还没有加载下来,alert(123)执行了。所以单纯使用这个readyState不太靠谱
那么jquery中是如何做的呢?jquery中用了一个IE才能识别的属性:document.documentElement.doScroll
这是个什么东东?好像从来没有见过? 这就是学习源码的好处,可以看看大师级人物是如何做处理的,并且我们可以从中取其精华,好不惬意!
兼容不支持该事件的浏览器
在IE8中,可以使用readystatechange事件来检测DOM文档是否加载完毕.在更早的IE版本中,可以通过每隔一段时间执行一次document.documentElement.doScroll("left")来检测这一状态,因为这条代码在DOM加载完毕之前执行时会抛出错误(throw an error)。
doScroll通过时readyState可能为interactive, 也可能为complete. 但是一定会在DOM结构稳定后, 图片加载完毕前执行.
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
} try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
} // and execute any waiting functions
jQuery.ready();
}
这是jquery的源码,通过异常捕获,如果DOM没有加载完,则会一直catch这个setTimeout ,直到dom加载完,执行以下try里面的doScroll
具体doScroll的详细含义大家可以从网上查查,我这里就不列举了
MSDN 关于 JScript 的一个方法有段不起眼的话,当页面 DOM 未加载完成时,调用 doScroll 方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了!
当然,doScroll的运用前提是页面中没有iframe,如果有iframe,那么只能是图片之类的全加载完毕才执行了。
从jQuery源码阅读看 dom load的更多相关文章
- jquery源码阅读(1)
每天坚持阅读一定量的的jquery代码,积少成多!加油加油! jquery-2.2.1的9161~9194行 1 if ( typeof define === "function" ...
- JQuery源码阅读记录
新建html文件,在浏览器中打开文件,在控制台输入consoole.log(window);新建html文件,引入JQuery后在浏览器中打开,在控制台同样输入consoole.log(window) ...
- jquery源码阅读笔记一
1. jquery无new的构造函数. 无new的构造函数是怎么实现的.比如我们一般这么用jQuery. $(".test").text(); 但是我们一般是这么写的. var t ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- jquery源码分析学习地址
http://www.ccvita.com/121.htmljQuery工作原理解析以及源代码示例http://www.cnblogs.com/haogj/archive/2010/04/19/171 ...
- jquery 源码分析学习地址
http://www.ccvita.com/121.htmljQuery工作原理解析以及源代码示例http://www.cnblogs.com/haogj/archive/2010/04/19/171 ...
随机推荐
- Mac 配置Spark环境scala+python版本(Spark1.6.0)
1. 从官网下载Spark安装包,解压到自己的安装目录下(默认已经安装好JDK,JDK安装可自行查找): spark官网:http://spark.apache.org/downloads.html ...
- iOS 统计App 的代码总行数
打开Terminal,cd 到项目的根目录下,输入以下命令 find . -name "*.m" -or -name "*.mm" -or -name &quo ...
- 新冲刺Sprint3(第七天)
一.Sprint介绍 商家功能模块持续更新着...... 二.Sprint周期 看板: 燃尽图:
- Ionic2学习笔记
Component nav: <ion-nav [root] = 'rootComponent'></ion-nav> ....import {Nav} from 'ionic ...
- ASP.NET Razor - C# 循环和数组
语句在循环中会被重复执行. For 循环 如果您需要重复执行相同的语句,您可以设定一个循环. 如果您知道要循环的次数,您可以使用 for 循环.这种类型的循环在向上计数或向下计数时特别有用: 实例 & ...
- Something you need to perform after RedHat 6.x installed
Something you need to perform after RedHat 6.x installed YUM Repos % yum update % rpm -Uvh http://do ...
- NewQuant的设计(二)——MatrixComputation的领域分析
NewQuant的设计——MatrixComputation的领域分析 MatrixComputation是NewQuant中最重要也是最大的一个模块,这个模块的领域分析要从回答几个问题开始. 一.矩 ...
- redis之(二十一)redis之深入理解Spring Redis的使用
关于spring redis框架的使用,网上的例子很多很多.但是在自己最近一段时间的使用中,发现这些教程都是入门教程,包括很多的使用方法,与spring redis丰富的api大相径庭,真是浪费了这么 ...
- mysql 序列与pg序列的比较
mysql序列(这里只谈innodb引擎): 在使用mysql的AUTO_INCREMENT时,使用AUTO_INCREMENT的字段必须建有索引,也可以为索引的一部分.当没有索引时会报错: ...
- C# WebApi 请求方式Post,返回Response
1.[FromBody]属性只能用在一个参数上,当Body中有多个参数要定义类型.一个参数的时候 key="",value="123",key为空才能取到值. ...