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

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

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

  1. jquery的$(document).ready()和onload的加载顺序

    最近在改一个嵌入在frame中的页面的时候,使用了jquery做效果,而页面本身也绑定了onload事件.改完后,Firefox下测试正常流畅,IE下就要等个十几秒jquery的效果才出现,黄花菜都凉 ...

  2. JS的window.onload与JQuery的$(document).ready(function(){})的区别

    前段时间去面试被问及JS的加载(onload)与jQuery中加载(ready)方法的区别,瞬时懵逼了,关于这个知识点平时还真没怎么注意. 最近先来无事便查了一下资料, onload 事件(W3c上给 ...

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

    jQuery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 windo ...

  4. 【jquery】$(document).ready() 与window.onload的区别

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1)执行时间  wind ...

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

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的.   1.执行时间 win ...

  6. Jquery中$(document).ready()与传统JavaScript中的window.onload方法的区别(2016/8/3)

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间       ...

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

    原博地址:http://blog.163.com/zhaoyanping_1125/blog/static/20132915320111129113723710/ * document.ready和o ...

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

    document.ready和onload的区别——JavaScript文档加载完成事件页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onlo ...

  9. javascript jquery document.ready window.onload

    网易 博客 下载LOFTER客户端 注册登录  加关注 凡图的编程之路 2012年7月从一个编程新手的点点滴滴 首页 日志 LOFTER 相册 博友 关于我     日志       关于我 Holy ...

随机推荐

  1. 《BI那点儿事》Microsoft 顺序分析和聚类分析算法

    Microsoft 顺序分析和聚类分析算法是由 Microsoft SQL Server Analysis Services 提供的一种顺序分析算法.您可以使用该算法来研究包含可通过下面的路径或“顺序 ...

  2. AngularJS的学习--ng-show/ng-hide/ng-if和ng-switch

    在Angular的原生指令中有这几个指令用来控制元素的展示与否,ng-show/ng-hide/ng-if和ng-switch. 在angular性能优化中,我们也常常会用到它. 我们看下他们的区别. ...

  3. Android在一个Activity中关闭另一个Activity

    比如有ActivityA, ActivityB,在ActivityB中关闭ActivityA. 解决方案: 1.在 ActivityA 里面设置一个静态的变量instance,初始化为this,在 A ...

  4. 搭建PHP开发环境

    通过两种方式搭建PHP开发环境,而这种开发环境实际是:Apache+MySQL+PHP.  第一种: 通过套件来安装和配置php开发环境. Apache+MySQL+PHP开发环境的搭建(一) 第二种 ...

  5. jQuery DOM操作

    对节点的操作 查找节点 查找节点可以直接利用jQuery选择器来完成,非常便利. 插入节点 jQuery提供了8种插入节点的方法. 序号 方法 描述 实例 1 append() 向每个匹配的元素内部追 ...

  6. d

    1.sql题1表名:成绩表姓名   课程       分数张三     语文       81张三     数学       75李四     语文       56李四     数学       9 ...

  7. 【读书笔记】--SQL基础概念复习

    主键:每个表,只能有一个主键,主键不能为NULL,且必须是唯一的.主键最好是由单个列组成,但这不是必须的,主键也可以是由多个列组成,如果表的两个列组合在一起能唯一标识一个行,而单个列不能,则可以将这两 ...

  8. 30天C#基础巩固-----序列化,集合

    关于集合的练习. ----->计算字符串每个字符出现的次数. Console.WriteLine("请输入?"); string input = Console.ReadLi ...

  9. Node.js系列基础学习-----回调函数,异步

    Node.js基础学习 Node.js回调函数 Node.js异步编程的直接体现就是回调,异步编程依托回调来实现,但不是异步.回调函数在完成任务后就会被调用,Node有很多的回调函数,其所有的API都 ...

  10. 开源通信(C#)__

    GitHub中的README文件,使用markdown格式的文件. 下面简单介绍下相关语法: 大标题: =================================== 大标题一般显示工程名,你 ...