ready()事件的應用,是你們再熟悉不過的了,學jQuery的第一步,最最多見的代碼:javascript
jQuery(document).ready(function () { }); jQuery(function () { }); $(document).ready(function () { }); $(function () { });
以上四行代碼的目的和效果都同樣——待DOM加載完成以後,執行傳入的function函數。html
再對jquery稍微熟悉一點的朋友可能知道,這裏的「待DOM加載完成」,不是window.onload事件,window.onload是指「DOM加載完成 + DOM相關的文件下載完成」。這裏的「DOM加載完成」,不包括「DOM相關的文件加載完成」。相關的事件是:java
問題就在這裏。若是知道了這兩個事件,那麼把傳入的function函數關聯到這兩個事件上就好了,而jquery中與ready相關的代碼洋洋灑灑的寫了那麼多,至於上百行代碼。這是爲什麼?jquery
緣由在於如下幾點:web
先看如下代碼:瀏覽器
//應用ready事件 $(function () { alert(10); }); $(function () { alert(20); }); $(function () { alert(30); });
以上代碼連續應用了三次ready方法,其實jquery是用自己的jquery.callbacks來處理的。主要代碼以下:異步
readyList = jQuery.Callbacks( "once memory" );
readyList.add( fn );
readyList.fireWith( document, [ jQuery ] );
"once":表明add進來的函數只被調用一次;函數
"memory":表明一旦readylist被執行過一次,那麼它後續添加進來的函數會當即按照執行時候的環境和參數執行。工具
以IE9+和其餘瀏覽器支持的DOMContentLoaded爲例。先看代碼:學習
// Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); }
DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); };
根據以上代碼可見,最終DOMContented事件執行的,實際上是jQUery.ready()這個工具函數。(注意,jquery.ready()和jquery(document).raedy()不同!!,前者是工具函數,後者是實例函數。)
這裏是經過定義一個DOMContentLoaded函數做爲橋樑來執行jquery.ready()函數的,這樣作的目的就是爲了即便的remove掉document的DOMContentLoaded事件的引用。
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
單獨把這兩行摘出來,能夠看明白,add完了以後,接着remove掉了,在這中間,巧妙的執行了jquery.ready(),這種用法值得學習!
反過來,若是像如下代碼那麼樣實現,document的DOMContentLoaded事件的引用將沒法及時刪除。
//反例 document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
另外,除了經過瀏覽器的DOMContentLoaded/onreadystatechange方法能夠調用jquery.ready()函數以外,還有一種巧妙的方式調用jquery.ready()函數。
在IE9如下的瀏覽器中,若是當前頁面是頂層(即沒有包含在iframe和friame元素中),調用html.doScroll(),直到不拋出異常,便可調用jquery.ready()函數。
1 if ( document.documentElement.doScroll && toplevel ) { 2 doScrollCheck(); 3 } 4 5 /*省略*/ 6 7 try { 8 // If IE is used, use the trick by Diego Perini 9 // http://javascript.nwbox.com/IEContentLoaded/ 10 document.documentElement.doScroll("left"); 11 } catch(e) { 12 setTimeout( doScrollCheck, 1 ); 13 return; 14 } 15 16 // and execute any waiting functions 17 jQuery.ready();
上文中講到,能夠經過瀏覽器的DOMContentLoaded/onreadystatechange事件,以及對html.doScroll()的檢測來調用jquery.ready()工具函數,jquery.ready()最終將會調用異步隊列的firewith()方法觸發傳入的全部事件。若是是經過js手動調用,也能夠經過jquery事件系統來調用。
readyList.fireWith( document, [ jQuery ] ); if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); }
其實這其中還有個jquery.holdready()方法用來延遲調用,不過比較簡單,也不經常使用,此處不說了。
可見,jQuery中的ready()事件並非咱們看起來那麼簡單,瞭解其原理的同時,也應該想一想咱們在本身設計系統的時候,考慮的時候全面。
我的感覺:想了解js到底該怎麼用,瞭解js的源碼和設計,是一個捷徑。