ready是先执行的,load后执行,DOM文档的加载步骤
在jq中在文档载入完毕后有这几种方式去执行指定函数:
$(document).ready(function() { // ...代码... }); //document ready 简写 $(function() { // ...代码... }); $(window).load(function() { // ...代码... });
$(function(){}) 的方式其实是 $(document).ready() 的简写,具体可以看看jq构造器那块。
ready与load谁先执行
这个问题在面试的时候也会经常被提到,ready是先执行的,load后执行,DOM文档的加载步骤:
(1) 解析HTML结构。 (2) 加载外部脚本和样式表文件。 (3) 解析并执行脚本代码。 (4) 构造HTML DOM模型。//ready (5) 加载图片等外部文件。 (6) 页面加载完毕。//load 分析原因
.ready() 都是作用于 window.onload 事件的。
jQuery.fn.ready = function( fn ) { // Add the callback jQuery.ready.promise().done( fn ); return this; };
当调用ready事件时,jq就会把函数添加到一个回调列表中。
而 .load() 作用的是为每个匹配元素的load事件绑定处理函数。
$(window).load( function(){ alert("文档加载完毕!"); } ); $("img").load( function(){ alert( "图片[" + this.alt + "]加载完毕!" ); } );
load的写法也发生了一些改变,1.8版本之后,load就抛弃了,只剩下ajax的load了,它的函数原型:
jQuery.fn.load = function( url, params, callback ) { //code... return this; }
因此在高版本中它的使用应该是:
$('#result').load('ajax/test.html', function() { alert('Load was performed.'); }); ready源码 // readyList.promise() === jQuery.ready.promise() var readyList; jQuery.fn.ready = function( fn ) { // promise后添加回调 jQuery.ready.promise().done( fn ); // 链式 return this; }; jQuery.extend({ // 此判断防止重复触发 isReady: false, // 需要几次jQuery.ready()调用,才会触发promise和自定义ready事件 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { // true,延迟次数 +1 jQuery.readyWait++; } else { // 无参数,消减次数 -1 jQuery.ready( true ); } }, // 触发promise和自定义ready事件 ready: function( wait ) { // ready(true)时,消减次数的地方。也能代替干ready()的事 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return; } // ready()调用时,标记dom已加载完成 jQuery.isReady = true; // ready(2881064151)能够设置isReady,只能消减默认的那1次 if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // 触发promise,jQuery.fn.ready(fn)绑定函数都被触发 readyList.resolveWith( document, [ jQuery ] ); // 触发自定义ready事件,并删除事件绑定 if ( jQuery.fn.triggerHandler ) { jQuery( document ).triggerHandler( "ready" ); jQuery( document ).off( "ready" ); } } }); // 解绑函数 function completed() { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); jQuery.ready(); } jQuery.ready.promise = function( obj ) { if ( !readyList ) { readyList = jQuery.Deferred(); // 判断执行到这时,是否已经加载完成 if ( document.readyState === "complete" ) { // 不再需要绑定任何监听函数,直接触发jQuery.ready。延迟一会,等代码执行完 setTimeout( jQuery.ready ); } else { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed, false ); // 个别浏览器情况,错过了事件仍可触发 window.addEventListener( "load", completed, false ); } } return readyList.promise( obj ); }; // 执行。生成deferred对象,绑定好监听逻辑 jQuery.ready.promise();
readyList = jQuery.Deferred(); 回调列表是 $.Deferred 对象,事件监听通过:
document.addEventListener( "DOMContentLoaded", completed, false ); window.addEventListener( "load", completed, false );
为了达到兼容不同浏览器,一个添加到 window 一个添加到 document ,通过 $.isReady 避免多次调用。
function completed() { document.removeEventListener( "DOMContentLoaded", completed, false ); window.removeEventListener( "load", completed, false ); jQuery.ready(); }
对事件进行解绑,调用 $.ready() :
readyList.resolveWith( document, [ jQuery ] );
执行异步对象里的函数队列。
load
load的实现就比较简单, jQuery.fn.load = function( url, params, callback ){} 它几乎与 $.get(url, data, success) 等价,因为它就是通过 $.ajax() 实现的,不同的是它的url可以包含一个空格或多个空格,紧接第一个空格的字符串则是决定所加载内容的 jQuery 选择器:
$("#result").load("ajax/test.html #container");
如果执行该方法,则会取回 ajax/test.html 的内容,不过然后, jQuery 会解析被返回的文档,来查找带有容器 ID 的元素。该元素,连同其内容,会被插入带有结果 ID 的元素中,所取回文档的其余部分会被丢弃。
off = url.indexOf(" "); if ( off >= 0 ) { selector = jQuery.trim( url.slice( off ) ); url = url.slice( 0, off ); }
最后来看看它ajax部分:
jQuery.ajax({ url: url, // if "type" variable is undefined, then "GET" method will be used type: type, dataType: "html", data: params }).done(function( responseText ) { // Save response for use in complete callback response = arguments; self.html( selector ? // If a selector was specified, locate the right elements in a dummy div // Exclude scripts to avoid IE 'Permission Denied' errors jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : // Otherwise use the full result responseText ); }).complete( callback && function( jqXHR, status ) { self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); });
self.html() 是使用浏览器的 .innerHTML 属性来解析被取回的文档,并把它插入当前文档。