jQuery Ready 與 Window onload 的區別(轉)

「咱們都知道,不少時候,在頁面加載完後都須要作一些相應的初始化動做.例如,運行某些js特效,設置表單等等.怎麼知道頁面加載完了呢?
一 般狀況下都是設置body標籤的onload監聽window的load事件.但load事件是要在頁面的元素所有加載完了才觸發的,若是頁面上圖片較多 或圖片太大,就會致使初始化的代碼未被執行的時候用戶就作了其它操做了. Jquery庫提供了一個很是方便好用的函數( $(selector).ready()),讓咱們能夠在頁面的dom加載完後就能夠作相應的操做(固然,這還得看用戶瀏覽器的支持).,而不用等待所有 元素加載完成.例如:
javascript

1 $(document).ready(function (){ alert('use in page script tag') }); 2 $(document).ready(function (){ alert('use in import js file') });


如今讓咱們來研究一下這個函數的實現.
原理:
在jquery腳本加載的時候,會設置一個isReady的標記,監聽 DOMContentLoaded事件(這個不是什麼瀏覽器都有的,不一樣瀏覽器,jquery運做方式不同).固然遇到調用ready函數的時候,若是 isReady未被設置,那就是說頁面未加載完,就會把要執行的函數用一個數組緩存起來,當頁面加載完後,再把緩存的函數一一執行.
Jquery中的詳細代碼分析: css

複製代碼
 1 ready: function(fn) {  2 // 綁定監聽器  3 bindReady();  4 // 若是 DOM 加載完成  5 if ( jQuery.isReady )  6 // 立刻運行此函數  7 fn.call( document, jQuery );  8 // 不然保存起來  9 else 10 // 把函數加入緩存數組中 11 jQuery.readyList.push( function() { return fn.call(this, jQuery); } ); 12 return this; 13 } 
複製代碼

讓咱們看看jquery若是實現不一樣瀏覽器dom加載完成的通知 bindReady()函數:java

複製代碼
 1 var readyBound = false;  2 function bindReady(){  3 if ( readyBound ) return;  4 readyBound = true;  5  6 // Mozilla,opera,webkitnightlies支持DOMContentLoaded事件  7 if ( document.addEventListener && !jQuery.browser.opera)  8 // 直接使用事件回調便可  9 document.addEventListener( "DOMContentLoaded", jQuery.ready, false ); 10 11 // 若是是ie而且不是嵌在frame中 12 // 就須要不斷地檢查文檔是否加載完 13 if ( jQuery.browser.msie && window == top ) (function(){ 14 if (jQuery.isReady) return; 15 try { 16 // 這個地方標記一下,在後面解析(1) 17 document.documentElement.doScroll("left"); 18 } catch( error ) { 19 //// 這個地方標記一下,在後面解析(2) 20 setTimeout( arguments.callee, 0 ); 21 return; 22 } 23 // and execute any waiting functions 24 jQuery.ready(); 25 })(); 26 27 if ( jQuery.browser.opera ) 28 document.addEventListener( "DOMContentLoaded", function () { 29 if (jQuery.isReady) return; 30 for (var i = 0; i < document.styleSheets.length; i++) // 標記(3) 31 if (document.styleSheets[i].disabled) { 32 setTimeout( arguments.callee, 0 ); 33 return; 34 } 35 // and execute any waiting functions 36 jQuery.ready(); 37 }, false); 38 39 if ( jQuery.browser.safari ) { 40 var numStyles; 41 (function(){ 42 if (jQuery.isReady) return; 43 if ( document.readyState != "loaded" && document.readyState != "complete" ) { // 標記(4) 44 setTimeout( arguments.callee, 0 ); 45 return; 46 } 47 if ( numStyles === undefined ) 48 numStyles = jQuery("style, link[rel=stylesheet]").length; 49 if ( document.styleSheets.length != numStyles ) { // 標記(5) 50 setTimeout( arguments.callee, 0 ); 51 return; 52 } 53 // and execute any waiting functions 54 jQuery.ready(); 55 })(); 56 } 57 58 // A fallback to window.onload, that will always work 59 jQuery.event.add( window, "load", jQuery.ready ); // 標記(6) 60 } 61 } 
複製代碼

1):這個主要是測出ie下的dom ready,原理在這裏http://javascript.nwbox.com/IEContentLoaded/,利用在ie下.當dom未完成解析 時,調用document的document.documentElement.doScroll(」left」)會出錯這個小技巧即可得知dom有沒有 ready了.
(2):setTimeout( arguments.callee, 0 )這句是表示延遲0秒調用,實際上它不會立刻就調用,而是會盡量快地調用,它告訴瀏覽器爲當前任何掛起的事件運行完事件句柄而且完成了文檔當前狀態的更 新後才調用. Arguments.callee便是外層的匿名函數,參數的調用者
(3):這個地方你也許以爲奇怪,爲何不在mozilla那裏一塊兒處理呢? 緣由就是opera的DOMContentLoaded事件發生後,其css樣式是還沒徹底可用的,因此要特殊處理,就是判斷每一個css的tag都是否是enable了.
(4),(5):safari中document.readyState的狀態爲loaded或complete時,css文件引入還未能肯定是否是解析完了的,因此要經過判斷其css文件數目
(6):最後,若是上面的hack都不支持的話…就用最保險的load事件,保證能執行到初始化代碼. jquery

相關文章
相關標籤/搜索