成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

jQuery的ready函數(shù)源碼解讀

soasme / 3324人閱讀

摘要:學習有許多途徑,我們今天從的函數(shù)開始。本例中的代碼都來自于腳本庫。我們在通過函數(shù)注冊事件處理之前,完成了頁面檢測代碼的注冊。當頁面完全加載之后,我們注冊的函數(shù)就被調(diào)用了。八參考的函數(shù)是如何工作的函數(shù)實現(xiàn)原理

如果你對$(document).ready()的理解也僅限于在DOM Tree繪制完畢后觸發(fā),那么,你也應該好好研究下ready的工作原理,因為,TST的面試官問過我這個問題。。。

一、關(guān)于jQuery

jQuery是一個偉大的腳本庫,由John Resig在 2006年1月的BarCamp NYC上釋出第一個版本。你可以在 http://jquery.com/ 下載到最新版本。這里以jQuery1.8.3為例分析。
學習jQuery有許多途徑,我們今天從jQueryready函數(shù)開始。本例中的代碼都來自于jQuery腳本庫。
如果你使用過jQuery,就必然使用過ready函數(shù),它用來注冊當頁面準備好之后可以執(zhí)行的函數(shù)。
問題來啦,我們的頁面什么時候準備好了呢?

二、onload事件

最基本的處理方式就是頁面的onload事件,我們在處理這個事件的時候,可以有多種方式,即可以通過HTML方式,直接寫在body元素的開始標記中,也可以使用事件注冊的方式來使用,這又可以分為DOM0方式和DOM2方式。再考慮到瀏覽器的兼容性,使用DOM2方式寫出來,如下所示。

if (document.addEventListener) {
    // A fallback to window.onload, that will always work
    window.addEventListener("load", jQuery.ready, false);

    // If IE event model is used
} else {
    // A fallback to window.onload, that will always work
    window.attachEvent("onload", jQuery.ready);
}
三、DOMContentLoaded事件

不過onload事件要等到所有頁面元素加載完成才會觸發(fā),包括頁面上的圖片等等。如果網(wǎng)頁上有大量的圖片,效果可想而知,用戶可能在沒有看到圖片的時候,就已經(jīng)開始操作頁面了,而這時我們的頁面還沒有初始化,事件還沒有注冊上,這豈不是太晚了!

除了大家熟知的onload事件之外, 與DOM中的onload事件相近的,我們還有 DOMContentLoaded事件可以考慮, 基于標準的瀏覽器支持這個事件, 當所有DOM 解析完以后會觸發(fā)這個事件。

這樣,對于基于標準的瀏覽器來說,我們還可以注冊這個事件的處理。這樣,我們可能更早地捕獲到加載完成的事件。

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);

}
四、onreadystatechange事件

不標準的瀏覽器怎么辦呢?

如果瀏覽器存在 document.onreadystatechange 事件,當該事件觸發(fā)時,如果 document.readyState=complete 的時候,可視為 DOM 樹已經(jīng)載入。

不過,這個事件不太可靠,比如當頁面中存在圖片的時候,可能反而在 onload 事件之后才能觸發(fā),換言之,它只能正確地執(zhí)行于頁面不包含二進制資源或非常少或者被緩存時作為一個備選吧。

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);

    // If IE event model is used
} else {
    // Ensure firing before onload, maybe late but safe also for iframes
    document.attachEvent("onreadystatechange", DOMContentLoaded);

    // A fallback to window.onload, that will always work
    window.attachEvent("onload", jQuery.ready);
}

DOMContentLoaded 函數(shù)在做什么呢?最終還是要調(diào)用 jQuery.ready 函數(shù)。

DOMContentLoaded = function() {
    if ( document.addEventListener ) {
        document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
        jQuery.ready();
    } else if ( document.readyState === "complete" ) {
        // we"re here because readyState === "complete" in oldIE
        // which is good enough for us to call the dom ready!
        document.detachEvent( "onreadystatechange", DOMContentLoaded );
        jQuery.ready();
    }
}
五、doScroll檢測法

MSDN 關(guān)于 JScript 的一個方法有段不起眼的話,當頁面 DOM 未加載完成時,調(diào)用 doScroll 方法時,會產(chǎn)生異常。那么我們反過來用,如果不異常,那么就是頁面DOM加載完畢了!

Diego Perini 在 2007 年的時候,報告了一種檢測 IE 是否加載完成的方式,使用 doScroll 方法調(diào)用。詳細的說明見這里。
原理是對于 IE 在非 iframe 內(nèi)時,只有不斷地通過能否執(zhí)行 doScroll 判斷 DOM 是否加載完畢。在本例中每間隔 50 毫秒嘗試去執(zhí)行 doScroll,注意,由于頁面沒有加載完成的時候,調(diào)用 doScroll 會導致異常,所以使用了 try -catch 來捕獲異常。

(function doScrollCheck() {
    if (!jQuery.isReady) {

        try {
            // Use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            top.doScroll("left");
        } catch (e) {
            return setTimeout(doScrollCheck, 50);
        }

        // and execute any waiting functions
        jQuery.ready();
    }
})();
六、document.readyState狀態(tài)

如果我們注冊 ready 函數(shù)的時間點太晚了,頁面已經(jīng)加載完成之后,我們才注冊自己的 ready 函數(shù),那就用不著上面的層層檢查了,直接看看當前頁面的 readyState 就可以了,如果已經(jīng)是 complete ,那就可以直接執(zhí)行我們準備注冊的 ready 函數(shù)了。不過 ChrisS 報告了一個很特別的錯誤情況,我們需要延遲一下執(zhí)行。

setTimeout 經(jīng)常被用來做網(wǎng)頁上的定時器,允許為它指定一個毫秒數(shù)作為間隔執(zhí)行的時間。當被啟動的程序需要在非常短的時間內(nèi)運行,我們就會給她指定一個很小的時間數(shù),或者需要馬上執(zhí)行的話,我們甚至把這個毫秒數(shù)設(shè)置為0,但事實上,setTimeout有一個最小執(zhí)行時間,當指定的時間小于該時間時,瀏覽器會用最小允許的時間作為setTimeout的時間間隔,也就是說即使我們把setTimeout的毫秒數(shù)設(shè)置為0,被調(diào)用的程序也沒有馬上啟動。

這個最小的時間間隔是多少呢?這和瀏覽器及操作系統(tǒng)有關(guān)。在John Resig的新書《Javascript忍者的秘密》一書中提到

Browsers all have a 10ms minimum delay on OSX and a(approximately) 15ms delay on Windows.(在蘋果機上的最小時間間隔是10毫秒,在Windows系統(tǒng)上的最小時間間隔大約是15毫秒)

另外,MDC中關(guān)于setTimeout的介紹中也提到,Firefox中定義的最小時間間隔(DOM_MIN_TIMEOUT_VALUE)是10毫秒,HTML5定義的最小時間間隔是4毫秒。既然規(guī)范都是這樣寫的,那看來使用setTimeout是沒辦法再把這個最小時間間隔縮短了。

這樣,通過設(shè)置為 1, 我們可以讓程序在瀏覽器支持的最小時間間隔之后執(zhí)行了。

// Catch cases where $(document).ready() is called after the browser event has already occurred.
// we once tried to use readyState "interactive" here, but it caused issues like the one
// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
if (document.readyState === "complete") {
    // 延遲 1 毫秒之后,執(zhí)行 ready 函數(shù)
    setTimeout(jQuery.ready, 1);
}
七、完整代碼
jQuery.ready.promise = function( obj ) {
    if ( !readyList ) {

        readyList = jQuery.Deferred();

        // Catch cases where $(document).ready() is called after the browser event has already occurred.
        // we once tried to use readyState "interactive" here, but it caused issues like the one
        // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
        if ( document.readyState === "complete" ) {
            // Handle it asynchronously to allow scripts the opportunity to delay ready
            setTimeout( jQuery.ready, 1 );

        // Standards-based browsers support DOMContentLoaded
        } else 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 );

        // If IE event model is used
        } else {
            // Ensure firing before onload, maybe late but safe also for iframes
            document.attachEvent( "onreadystatechange", DOMContentLoaded );

            // A fallback to window.onload, that will always work
            window.attachEvent( "onload", jQuery.ready );

            // If IE and not a frame
            // continually check to see if the document is ready
            var top = false;

            try {
                top = window.frameElement == null && document.documentElement;
            } catch(e) {}

            if ( top && top.doScroll ) {
                (function doScrollCheck() {
                    if ( !jQuery.isReady ) {

                        try {
                            // Use the trick by Diego Perini
                            // http://javascript.nwbox.com/IEContentLoaded/
                            top.doScroll("left");
                        } catch(e) {
                            return setTimeout( doScrollCheck, 50 );
                        }

                        // and execute any waiting functions
                        jQuery.ready();
                    }
                })();
            }
        }
    }
    return readyList.promise( obj );
};

那么,又是誰來調(diào)用呢?當然是需要的時候,在我們調(diào)用 ready 函數(shù)的時候,才需要注冊這些判斷頁面是否完全加載的處理,這段代碼在 1.8.3 中位于代碼的 #244 行,如下所示:

ready: function( fn ) {
    // Add the callback
    jQuery.ready.promise().done( fn );

    return this;
}

在頁面上引用 jQuery 腳本庫之后,執(zhí)行了 jQuery 的初始化函數(shù),初始化函數(shù)中創(chuàng)建了 ready 函數(shù)。我們在通過 ready 函數(shù)注冊事件處理之前,jQuery完成了頁面檢測代碼的注冊。這樣。當頁面完全加載之后,我們注冊的函數(shù)就被調(diào)用了。

八、參考

1.jQuery 的 ready 函數(shù)是如何工作的?
2.jQuery ready函數(shù)實現(xiàn)原理
3.deferred.done()

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79717.html

相關(guān)文章

  • FE.SRC-逐行分析jQuery2.0.3源碼-完整筆記

    摘要:根據(jù)項目選型決定是否開啟。為了壓縮,可維護為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調(diào)用的是這個原型實際上。功能檢測統(tǒng)一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...

    Lin_R 評論0 收藏0
  • FE.SRC-逐行分析jQuery2.0.3源碼-完整筆記

    摘要:根據(jù)項目選型決定是否開啟。為了壓縮,可維護為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調(diào)用的是這個原型實際上。功能檢測統(tǒng)一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...

    褰辯話 評論0 收藏0
  • jQuery學到幾件事情

    摘要:最近想看一下源碼,搜到了這樣一篇博客從源碼學到的件事情本文基于這篇視頻博客,提煉了一些內(nèi)容,分享給大家。的狀態(tài)選擇符,比如存放在里面 最近想看一下jQuery源碼,搜到了這樣一篇博客《從jQuery源碼學到的10件事情》http://www.paulirish.com/2010/10-things-i-learned-from-the-jquery-source/ 本文基于這篇視頻博...

    jlanglang 評論0 收藏0
  • jQuery3.3.1源碼閱讀(一)

    摘要:入口結(jié)構(gòu)具體代碼抽離結(jié)構(gòu)如下涉及到的知識解析函數(shù)時的規(guī)則函數(shù)定義和函數(shù)表達式閉包解析函數(shù)的規(guī)則解析器會在遇到時將其認為是函數(shù)定義而非函數(shù)表達式函數(shù)定義和函數(shù)表達式函數(shù)定義函數(shù)表達式閉包閉包函數(shù)中的函數(shù),本質(zhì)是指作用域內(nèi)的作用域閉包舉例綜合以 1.入口結(jié)構(gòu) ( function( global, factory ) { use strict; if ( t...

    王晗 評論0 收藏0
  • 前端基礎(chǔ)進階(十一):詳細圖解jQuery對象,以及如何擴展jQuery插件

    摘要:而在構(gòu)造函數(shù)中,返回了的實例對象。在中直接返回過的實例,這里的是的真正構(gòu)造函數(shù)最后對外暴露入口時,將字符與對等起來。因此當我們直接使用創(chuàng)建一個對象時,實際上是創(chuàng)建了一個的實例,這里的正真構(gòu)造函數(shù)是原型中的方法。 showImg(https://segmentfault.com/img/remote/1460000008749398); 早幾年學習前端,大家都非常熱衷于研究jQuery源...

    RebeccaZhong 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<