jQuery的document ready与 onload事件——你真的思考过吗?

在进行实验和资料查询时,我遇到了几个关键问题:

1. window.onload到底是什么加载完触发?

2. body为什么会有onload事件?

3. 为什么是window.onload,而不是document.onload?

4. document ready到底是什么ready,DOM渲染完成?

5. jQuery怎么实现$(document).ready?

6. jQuery的ready,还能ready什么?

7. jQuery的document ready就一定比window.onload快吗?

8. 为什么外部script文件放页面内容后面好,是一定的吗?

onload

load是一个事件,会在页面包含文件资源加载完成后触发。

支持该事件的HTML标签:

body、frame、frameset、iframe、img、link、script。

这里有两点我很在意的是:

1. 其他标签是没有该事件,所以不要胡乱用。

2. 就如我开头提的问题之一,为什么body会有onload?(Question 2)

首先,我为什么有这个疑问,因为可以看出的是,支持该事件的其他标签都是为了加载标签里的src资源,而body显然不是。

我在《JavaScript高级程序设计》找到一个合理的解释:

一般来说,在window上面发生的任何事件都可以在body元素中通过相应的特性来指定,因为在HTML中无法访问window元素。这样是为了保证向后兼容的权宜之计,但所有浏览器都能很好地支持这种方式。

结论:为了对应上window.onload,body标签才有onload。

支持该事件的JavaScript对象:

image、window。

这里有两个问题我很在意:

1. window.onload到底是什么加载完触发?(Question 1)

依资料记载,当页面完全加载后(包括所有图像、JavaScript文件等外部资源),就会触发该事件。这方式跟在body上写onload效果是一样的。

2. 为什么是window.onload,而不是document.onload? (Question 3)

按上面那个问题的解释,明明是整个document里面完全加载后触发,那为什么是window.onload(在window上是什么鬼),而不是document.onload?

还是按《JavaScript高级程序设计》上解释:

根据“DOM2级事件”规范,应该是在document而非window上面触发load事件。但是,所有浏览器都在window上面实现了该事件,以确保向后兼容。

结论:道理是这么道理,但大家都这么干了。

jQuery document ready

从原生js来讲,并没有ready这种事件。

那么 document ready到底是什么ready了?(Question 4)

按资料说明,这个事件指的是文档结构(DOM)加载完成触发的。

PS:这解释还算合理,就放过这问题。

那jQuery怎么实现$(document).ready?(Question 5)

下面我尝试解析jquery3.0.0版本(兼容IE9+,现代浏览器)里面关于ready事件的实现!

注意:

版本我选择比较新的3.0.0,相比于较旧版本(例1.x)的,里面的实现会简单一些,因为舍弃一些兼容代码。不过实现的原理是一样,倒不需要多个版本都详看。

原理:

在jquery脚本加载的时候,会监听DOMContentLoaded事件(监听load是补救后路)。当事件触发时候,会执行ready事件的回调。

代码:

var readyList = jQuery.Deferred();

//保存所有DOM加载完后执行的函数。
jQuery.fn.ready = function( fn ) {
     readyList.then( fn );
     return this;
};

jQuery.extend( {

     //标记DOM ready事件是否触发过。
     isReady: false,

     // A counter to track how many items to wait for before
     // the ready event fires. See #6781
     readyWait: 1,

     // Hold (or release) the ready event
     holdReady: function( hold ) {
          if ( hold ) {
               jQuery.readyWait++;
          } else {
               jQuery.ready( true );
          }
     },

     // Handle when the DOM is ready
     ready: function( wait ) {

          // Abort if there are pending holds or we‘re already ready
          if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
               return;
          }

          // Remember that the DOM is ready
          jQuery.isReady = true;

          // If a normal DOM Ready event fired, decrement, and wait if need be
          if ( wait !== true && --jQuery.readyWait > 0 ) {
               return;
          }

          // If there are functions bound, to execute
          readyList.resolveWith( document, [ jQuery ] );
     }
} );

jQuery.ready.then = readyList.then;

// The ready event handler and self cleanup method
function completed() {
     document.removeEventListener( "DOMContentLoaded", completed );
     window.removeEventListener( "load", completed );
     jQuery.ready();
}

// Catch cases where $(document).ready() is called
// after the browser event has already occurred.
// Support: IE <=9 - 10 only
// Older IE sometimes signals "interactive" too soon
if ( document.readyState === "complete" ||
     ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {

     // Handle it asynchronously to allow scripts the opportunity to delay ready
     window.setTimeout( jQuery.ready );

} else {
     // Use the handy event callback
     document.addEventListener( "DOMContentLoaded", completed );

     //其实最奸诈是这里,在不支持DOMContentLoaded事件的浏览器,用load事件代替
     // A fallback to window.onload, that will always work
     window.addEventListener( "load", completed );
}

特别地方:

1. 注册事件是用addEventListener,所以该jquery版本应该是只支持IE9+。

2. jQuery的ready,还能ready什么?(Question 6)

ready函数仅能用于当前document,因此无需选择器,所以不能ready其他元素。

三种姿势使用该函数:

$(document).ready(function)
$().ready(function)
$(function)

谁更快?

jQuery的document ready就一定比window.onload快吗?(Question 7)

我写了一个例子来实验:

<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8"/>
<title>加载时机</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"
onload="console.log(‘jquery.js loaded‘)"></script>
<script>
     console.log(‘define functions‘);
     function load(type, info){
          console.log(type + ‘ onload ‘ + (info || ""), new Date().getTime());
     }
     $(document).ready(function () {
          load(‘document ready‘);
     });
     document.onload = function () {
          load(‘document‘);
     };
     window.onload = function () {
          load(‘window‘);
     };
     window.addEventListener("load",function(){
          load(‘window addEventListener‘);
     });
     document.addEventListener( "DOMContentLoaded", function () {
          load(‘DOMContentLoaded‘);
     });
</script>
</head>
     <body onload="load(‘body‘)">
          <div onload="load(‘text‘)">test</div>
          <img onload="load(‘img‘,1)" src="http://www.deskcar.com/desktop/else/2013714232149/17.jpg" />
          <img onload="load(‘img‘,2)" src="http://www.deskcar.com/desktop/else/2013714232149/16.jpg" />
          <script onload="load(‘js‘)" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react.min.js"></script>
     </body>
</html>

这种大体有两种结果:

首次加载:

二次加载:

第一种情况非常符合我们的想法,ready比onload快,顺序也比较合理。

而第二种情况就有些怪异,应该依照上面jquery ready事件的实现,那ready应该要DOMContentLoaded后面啊。我思来想去,我觉得这是个误会,由于二次加载时利用到缓存,导致文件资源都很快加载,各个事件触发的时间非常相近,顺序也不定,就给人一种ready顺序不对之感,大家应该发现这几个事件都是在几十毫秒之内触发。

PS:js执行需要时间,几十毫秒不同的顺序我觉得很正常。另个尝试几次,二次加载顺序确实会有变化,但时间都很相近。

所以,jQuery的document ready不一定比window.onload快执行。

为什么外部script文件放页面内容后面好?

script执行顺序:

《JavaScript高级程序设计》说过——无论如何包含代码,只要不存在defer和async属性,浏览器都会按照<script>元素在页面中出现的先后顺序对它们依次进行解析。换句话说,在第一个<script>元素包含的代码解析完成后,第二个<script>包含代码才会被解析,然后才是第三个.....

放head元素里:

<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8"/>
<title>Example</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react.min.js"></script>
</head>
     <body>

     </body>
</html>

在head元素里包含所有JavaScript文件,就必须等到全部JavaScript代码都被下载、解析和执行完成以后,才能呈现页面的内容(浏览器在遇到<body>标签时才开始呈现内容)。在需要很多JavaScript文件时候,浏览器呈现页面会出现明显的延迟,延时期间浏览器是一片空白。

所以,外部script文件放页面内容后面。这样,在解析JavaScript代码之前,页面内容将完全呈现出来。

一定是放页面内容后面吗?

有种情况是JavaScript放哪里都一样的,那就是内容是依赖JavaScript的执行渲染时候,放哪都一样。

总结

虽然这篇文章是简单的问题,但有时我们就是连简单的东西都没搞懂,还以为我们懂了。

本文为原创文章,转载请保留原出处,方便溯源,如有错误地方,谢谢指正。

本文地址 :http://www.cnblogs.com/lovesong/p/5641834.html

时间: 2024-10-05 18:33:54

jQuery的document ready与 onload事件——你真的思考过吗?的相关文章

Jquery中$(document).ready() 和 JavaScript中的window.onload方法 比较

Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个(最后一个)       

javascript的window.onload()方法和jQuery的$(document).ready()的对比

jQuery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 window.onload不能同时编写多个,如果有多个window.onload方法,只会执行一个 ,后面会覆盖前面的. $

jQuery中$(document).ready()和window.onload的区别

 $(document) ready()和window onload在表面上看都是页面加载时我们就去执行一个函数或动作,但是在具体的细节上$(document) ready()和window onload还是有区别的. 最基本的区别 1.执行时间 window.onload必须等到页面内包括图片.flash等的所有元素加载完毕后才能执行.$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 如<p>图片视频等</p>(假设页面只有这一个标签),wi

document.ready和onload的区别——JavaScript文档加载完成事件

文章转自:http://blog.csdn.net/kk5595/article/details/5713209 页面加载完成有两种事件,一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件),二是onload,指示页 面包含图片等文件在内的所有元素都加载完成.(可以说:ready 在onload 前加载!!!) 我的理解: 一般样式控制的,比如图片大小控制放在onload 里面加载; 而:jS事件触发的方法,可以在ready 里面加载; 更多内容戳这里:http://blog.

JS 页面加载触发事件 document.ready和onload的区别

JS 页面加载触发事件 document.ready和onload的区别 document.ready和onload的区别——JavaScript文档加载完成事件 页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onload,指示页面包含图片等文件在内的所有元素都加载完成. 1.Dom Ready 用jQ的人很多人都是这么开始写脚本的: $(function(){       // do something }); 例如: $(functi

javascript jquery document.ready window.onload

网易 博客 下载LOFTER客户端 注册登录 加关注 凡图的编程之路 2012年7月从一个编程新手的点点滴滴 首页 日志 LOFTER 相册 博友 关于我 日志 关于我 Holyson 闻道有先后,术业有专攻 加博友   关注他 文章分类 ·css(2) ·.net控件事件(3) ·帐号密码(0) ·JS与JQ(12) ·sql server指南(5) ·杂谈(2) ·C#基础指南(18) ·.net成长篇(38) ·更多 > LOFTER精选 注册免费冲印20张照片 > 网易新闻 清华毕业学

jquery中$(document).ready(function(){//todo});window.onload时间线关系

1.基于DOM的解析加载过程,即:document.readystate状态, 其有如下四个状态: a.uninitiated,未初始化状态. b.loading,dom开始解析. c.loaded,dom解析完成.document.ready触发,然后再加载其他东西(图片.延迟加载的js代码等). d.complete,所需要的图片 异步js等也加载完成,整个页面不在请求数据. 2.例子如下: document.onreadystatechange = function(){ if(docum

js中window.onload 与 jquery中$(document.ready()) 测试

js中window.onload 与 jquery中$(document.ready())区别,验证代码如下(调换js代码和Jquer代码书写顺序测试,运行结果一样,因此与代码书写位置没关系): <html> <head> <script type='text/javascript' src='jquery-1.11.1.min.js'></script> <script type='text/javascript'> $(document).r

Jquery中&quot;$(document).ready(function(){ })&quot;函数的使用详解

Jquery是优秀的Javascrīpt框架,$是jquery库的申明,它很不稳定(我就常遇上),换一种稳定的写法jQuery.noConflict(); jQuery(document).ready(function(){}); 使用jQuery的好处是它包装了各种浏览器版本对DOM对象(javascript的DOM对象你应该知道吧,就是它了)的操作. 比如jquery写法: 1 $("div p"); // (1) 2 $("div.container"); /