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
jQuery的document ready与 onload事件——你真的思考过吗?的更多相关文章
- jquery的$(document).ready()和onload的加载顺序
最近在改一个嵌入在frame中的页面的时候,使用了jquery做效果,而页面本身也绑定了onload事件.改完后,Firefox下测试正常流畅,IE下就要等个十几秒jquery的效果才出现,黄花菜都凉 ...
- JS的window.onload与JQuery的$(document).ready(function(){})的区别
前段时间去面试被问及JS的加载(onload)与jQuery中加载(ready)方法的区别,瞬时懵逼了,关于这个知识点平时还真没怎么注意. 最近先来无事便查了一下资料, onload 事件(W3c上给 ...
- javascript的window.onload()方法和jQuery的$(document).ready()的对比
jQuery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 windo ...
- 【jquery】$(document).ready() 与window.onload的区别
Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1)执行时间 wind ...
- Jquery中$(document).ready() 和 JavaScript中的window.onload方法 比较
Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 win ...
- Jquery中$(document).ready()与传统JavaScript中的window.onload方法的区别(2016/8/3)
Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的. 1.执行时间 ...
- JS 页面加载触发事件 document.ready和onload的区别(转)
原博地址:http://blog.163.com/zhaoyanping_1125/blog/static/20132915320111129113723710/ * document.ready和o ...
- JS 页面加载触发事件 document.ready和onload的区别
document.ready和onload的区别——JavaScript文档加载完成事件页面加载完成有两种事件: 一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件): 二是onlo ...
- javascript jquery document.ready window.onload
网易 博客 下载LOFTER客户端 注册登录 加关注 凡图的编程之路 2012年7月从一个编程新手的点点滴滴 首页 日志 LOFTER 相册 博友 关于我 日志 关于我 Holy ...
随机推荐
- JSP网站开发基础总结《三》
经过前两篇的总结,我想大家一定迫不及待的想学习今天的关于jsp与mysql的数据库连接的知识了.既然需要连接mysql数据库,你首先需要保证你的电脑已经安装过mysql数据库,mysql数据库的安装步 ...
- poj2513Colored Sticks(无向图的欧拉回路)
/* 题意:将两端涂有颜色的木棒连在一起,并且连接处的颜色相同! 思路:将每一个单词看成一个节点,建立节点之间的无向图!判断是否是欧拉回路或者是欧拉路 并查集判通 + 奇度节点个数等于2或者0 */ ...
- 【原创】.NET读写Excel工具Spire.Xls使用(2)Excel文件的控制
本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html .NET读写Excel工具Spire.Xls使用文章 ...
- JavaWeb:Web与HTTP协议简介
JavaWeb:Web与HTTP协议简介 Web的概念 什么是Web: Web是网络上使用最广泛的分布式应用架构. 旨在共享分布在网络上的各个Web服务器中的所有互相连接的信息. 三个特征: 用HTM ...
- [C] C++对C的部分扩充
C语言只允许变量在程序(或函数)开始处定义,而C++允许变量在程序的任何位置定义. C语言中没有定义作用域限定运算符. C语言中没有布尔类型. C++中关于枚举类型和结构类型的定义更加简洁. C++新 ...
- VMware中网络设置之Bridged
1.设置linux虚拟机Bridged模式. 2.查找网关地址:点击虚拟机工具栏编辑---Virtual Network Editor,选中VMnet0,然后在Bridged to 下拉框中选择可以本 ...
- SQL--局部变量
取值的话:print @变量名, 变量不设置值的话,默认打印出来是:NULL, 输出变量的值:
- 我的vim配置文件
强烈拥护开源精神,高举开源大旗,今天我就分享下我自己结合网上还有自己实际使用配的vimrc,可以给各位参考下,不要见笑,具体说明我在rc里写的也很详细,可以具体看下,也希望可以借这个机会能多认识认识几 ...
- UEditor 1.4.3.1.NET版本上传配置备忘录
UEditor用起来还是挺方便的,下面是记录一下在上传中的配置问题(主要是上传图片的配置,其他的都是类似的). 我下载的是UEditor 1.4.3.1 .NET版本. 官网的配置说明地址为 http ...
- ASP.NET MVC 使用Jquery Uploadify 在非IE浏览器下Http Error的解决方案
解决Uploadify上传控件在非IE浏览器中不工作,需要做如下2步修改: 1.Global.asax文件中,实现Application_BeginRequest函数: void Applicatio ...