jQuery1.0源代碼分析之ready函數(四) – Javascript教程_JS教程_技術文章 – 程式設計聯盟

 

上幾篇文章已經說明白瞭,jQuery的基本框架設計。這一篇我們來細說一下,jQuery的ready函數。

 

 

jQuery的ready函數,就相當於c語言裡的main函數。代表的意義是當Dom文檔加載成功,就開始執行ready函數。

 

Dom文檔加載成功綁定的是document的DOMContentLoaded事件,而網頁加載完成綁定的是window的load事件,前者要比後者早很多。

 

 

有一個很好的在線例子,是微軟提供的。地址如下

https://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 

    // https://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 ); 

     

}; 

早期的時候,可能隻有火狐和Opera支持DomContentLoaded事件,IE和safari都不支持。現在來看是除瞭IE都支持瞭,IE 9也是支持的。

 

上面的代碼有一處亮點就是對IE瀏覽器的處理,用瞭script標簽的defer屬性,這個defer屬性是IE獨有的。當它被設為true的時候,表示這段script要等文檔加載好瞭才執行。

作者 baozhifei

發佈留言