最近做一个项目,在上一篇文章里面写了一个插件:jQuery滚动固定插件,刚开始时在本地测试,发现都没问题,后来架设到服务器上,发现浮动的末位置总是不对,总以为是哪些代码冲突或者是插件写得不完善,后来开启了调试。发现那个底部Bottom参数的高度随着刷新浏览器在变化,不可能啊。元素是固定在那里的。没有想到是jQuery的原因。
以浏览器装载文档为例,页面加载完毕后,浏览器会通过Javascript为DOM元素添加事件,在常规的Javascript代码中,通常使用window.onload方法,而在Jquery中,使用的是$(document).ready()方法。由于在$(document).ready()方法内注册的事件,只要DOM就绪就会被执行,因此可能此时元素的关联文件未下载完。例如与图片有关的 html下载完毕,并且已经解析为DOM树了,但很有可能图片还没有加载完毕,此时图片的高度和宽度不一定有效。要解决这个问题,可以 使用Jquery中另一个关于页面加载的方法---load()方法。Load()方法会在元素的onload事件中绑定一个处理函数。
如果处理函数绑定 给window对象,则会在所有内容(包括窗口、框架、对象和图像等)加载完毕后触发,如果处理函数绑定在元素上,则会在元素的内容加载完毕后触发。
下面给出jQuery ready与window.onload的区别
window.load |
$(document).ready() |
|
执行时机 |
必须等待网页中所有的内容加载完毕后(包括图片)才能执行 |
网页中所有DOM结构绘制完毕后就执行,可以能DOM元素关联的内容并没有加载完 |
编写个数 |
不能同时编写多个 以下代码无法正确执行: window.onload = function(){ alert("caibaojian"); }; window.onload = function(){ alert("caibaojian.com"); }; 结果只输出第二个 |
能同时编写多个 以下代码正确执行: $(document).ready(function(){ alert("Hello Caibaojian"); }); $(document).ready(function(){ alert("Hello caibaojian.com"); }); 结果两次都输出 |
简化写法 |
无 |
$(function(){ // do something }); |
Jquery代码如下:
在jquery脚本加载的时候,会设置一个isReady的标记,监听DOMContentLoaded事件(这个不是什么浏览器都有的,不同浏览器,jquery运作方式不一样).当然遇到调用ready函数的时候,如果isReady未被设置,那就是说页面未加载完,就会把要执行的函数用一个数组缓存起来,当页面加载完后,再把缓存的函数一一执行.
Jquery中的详细代码分析:
代码如下 | 复制代码 |
ready: function(fn) { // 绑定监听器 bindReady(); // 如果 DOM 加载完成 if ( jQuery.isReady ) // 马上运行此函数 fn.call( document, jQuery ); // 否则保存起来 else // 把函数加入缓存数组中 jQuery.readyList.push( function() { return fn.call(this, jQuery); } ); return this; } |
让我们看看jquery如果实现不同浏览器dom加载完成的通知 bindReady()函数:
代码如下 | 复制代码 |
var readyBound = false; function bindReady(){ if ( readyBound ) return; readyBound = true; // Mozilla,opera,webkitnightlies支持DOMContentLoaded事件 // 如果是ie并且不是嵌在frame中 if ( jQuery.browser.opera ) if ( jQuery.browser.safari ) { // A fallback to window.onload, that will always work |
1):这个主要是测出ie下的dom ready, 利用在ie下.当dom未完成解析时,调用document的document.documentElement.doScroll(”left”)会出错这个小技巧便可得知dom有没有ready了.
(2):setTimeout( arguments.callee, 0 )这句是表示延迟0秒调用,实际上它不会马上就调用,而是会尽可能快地调用,它告诉浏览器为当前任何挂起的事件运行完事件句柄并且完成了文档当前状态的更新后才调用. Arguments.callee即是外层的匿名函数,参数的调用者
(3):这个地方你也许觉得奇怪,为什么不在mozilla那里一起处理呢? 原因就是opera的DOMContentLoaded事件发生后,其css样式是还没完全可用的,所以要特殊处理,就是判断每个css的tag都是不是enable了.
(4),(5):safari中document.readyState的状态为loaded或complete时,css文件引入还未能确定是不是解析完了的,所以要通过判断其css文件数目
(6):最后,如果上面的hack都不支持的话…就用最保险的load事件,保证能执行到初始化代码