上幾篇文章已經說明白了,jQuery的基本架構設計。這一篇我們來細說一下,jQuery的ready函數。
jQuery的ready函數,就相當於c語言裡的main函數。代表的意義是當Dom文檔載入成功,就開始執行ready函數。
Dom文檔載入成功綁定的是document的DOMContentLoaded事件,而網頁載入完成綁定的是window的load事件,前者要比後者早很多。
有一個很好的線上例子,是微軟提供的。地址如下
http://ie.microsoft.com/testdrive/HTML5/DOMContentLoaded/Default.html,你訪問的時候最好用IE 9或者其他支援標準的瀏覽器。
jQuery的ready函數使用起來也很簡單,有兩種方法,代碼如下:
$(document).ready(function() {
// start here
});
$(function() {
// start here
});
這兩種方法區別不大,用那個都可以。
我們來看一下jQuery的代碼是如何處理的
function jQuery(a,c) {
// Shortcut for document ready (because $(document).each() is silly)
if ( a && a.constructor == Function && jQuery.fn.ready )
return jQuery(document).ready(a);
}
很明顯,當我們使用第二種方法的時候,jQuery也是走的第一種方法。也就是說第二種方法是第一種的捷徑。都是調用jQuery的原型方法ready函數。
我們來看一下jQuery原型方法的ready函數。參數f就是我們傳進來的匿名函數,當isReady標誌變數是true的時候,直接執行f函數,否則,把f函數放到readyList數組中去。
jQuery.fn.extend({
ready: function(f) {
// If the DOM is already ready
if ( jQuery.isReady )
// Execute the function immediately
f.apply( document );
// Otherwise, remember the function for later
else {
// Add the function to the wait list
jQuery.readyList.push( f );
}
return this;
}
});
很好理解isReady就是標誌變數,當Dom文檔載入好了,就設定為true,readyList就是存放我們傳進來的匿名函數的數組。
所以jQuery的靜態方法ready就是當isReady為true的時候,把readyList中的函數統統執行一遍。
jQuery.extend({
/*
* All the code that makes DOM Ready work nicely.
*/
isReady: false,
readyList: [],
// Handle when the DOM is ready
ready: function() {
// Make sure that the DOM is not already loaded
if ( !jQuery.isReady ) {
// Remember that the DOM is ready
jQuery.isReady = true;
// If there are functions bound, to execute
if ( jQuery.readyList ) {
// Execute all of them
for ( var i = 0; i < jQuery.readyList.length; i++ )
jQuery.readyList[i].apply( document );
// Reset the list of functions
jQuery.readyList = null;
}
}
}
});
最後,是ready函數執行的關鍵,就是註冊DomContentLoad事件,但是因為各個瀏覽器的實現不一樣,所以觸發事件的方法也不大一樣。代碼如下
new function(){
// If Mozilla is used
if ( jQuery.browser.mozilla || jQuery.browser.opera ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
// If IE is used, use the excellent hack by Matthias Miller
// http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
} else if ( jQuery.browser.msie ) {
// Only works if you document.write() it
document.write("<scr" + "ipt id=__ie_init defer=true " +
"src=//:><\/script>");
// Use the defer script hack
var script = document.getElementById("__ie_init");
script.onreadystatechange = function() {
if ( this.readyState == "complete" )
jQuery.ready();
};
// Clear from memory
script = null;
// If Safari is used
} else if ( jQuery.browser.safari ) {
// Continually check to see if the document.readyState is valid
jQuery.safariTimer = setInterval(function(){
// loaded and complete are both valid states
if ( document.readyState == "loaded" ||
document.readyState == "complete" ) {
// If either one are found, remove the timer
clearInterval( jQuery.safariTimer );
jQuery.safariTimer = null;
// and execute any waiting functions
jQuery.ready();
}
}, 10);
}
// A fallback to window.onload, that will always work
jQuery.event.add( window, "load", jQuery.ready );
};
早期的時候,可能只有Firefox和Opera支援DomContentLoaded事件,IE和safari都不支援。現在來看是除了IE都支援了,IE 9也是支援的。
上面的代碼有一處亮點就是對IE瀏覽器的處理,用了script標籤的defer屬性,這個defer屬性是IE專屬的。當它被設為true的時候,表示這段script要等文檔載入好了才執行。
作者 baozhifei