jQuery-1.9.1源码分析系列(六) 延时对象应用——jQuery.ready
還記不記得jQuery初始化函數jQuery.fn.init中有這樣是一個分支
//document ready簡便寫法$(function(){…}) } else if ( jQuery.isFunction( selector ) ) {return rootjQuery.ready( selector ); }所以$(fn)===$(document).ready(fn)。
來看一下jQuery.fn.ready的源碼
ready: function( fn ) {// Add the callback jQuery.ready.promise().done( fn );return this; }很明顯在jQuery.ready.promise函數中設置了延時,當延時對象解決的時候執行fn函數。
主要的處理流程:
創建一個延時對象,并將文檔準備好后的處理事件添加到該延時對象成功事件列表上。
jQuery.ready.promise = function( obj ) { if ( !readyList ) {readyList = jQuery.Deferred();...
}return readyList.promise( obj ); }
添加文檔準備狀態的監聽函數(jQuery.ready.promise函數片段)
//標準瀏覽器支持DOMContentLoaded事件} else if ( document.addEventListener ) {//綁定DOMContentLoaded事件和響應函數,響應函數會解決延時document.addEventListener( "DOMContentLoaded", completed, false );//回退到window.onload事件綁定,所有的瀏覽器都支持window.addEventListener( "load", completed, false );//如果是IE事件模型} else {//確保在onload之前執行延時,可能時間比較遲,但是對于iframes來說比較安全document.attachEvent( "onreadystatechange", completed );//回退到window.onload事件綁定,所有的瀏覽器都支持window.attachEvent( "onload", completed );//如果IE并且不是一個frame//不斷地檢查,看是否該文件已準備就緒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 );}//移除之前綁定的事件 detach();//執行延遲 jQuery.ready();}})();}}一旦監聽到文檔準備完成,則調用jQuery.ready執行延時對象的成功回調列表:即所有通過jQuery.ready(fn)【或jQuery(fn)】方式添加的函數fn。
//ready事件處理函數 completed = function( event ) {// readyState === "complete"在老版本IE上適用if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {detach();jQuery.ready();} }, //清除ready事件綁定 detach = function() {if ( document.addEventListener ) {document.removeEventListener( "DOMContentLoaded", completed, false );window.removeEventListener( "load", completed, false );} else {document.detachEvent( "onreadystatechange", completed );window.detachEvent( "onload", completed );} }; //處理當DOM準備完成 jQuery.ready: function( wait ) { ... //設置DOM已經準備好的標志 jQuery.isReady = true; ... //執行綁定的延時事件 readyList.resolveWith( document, [ jQuery ] ); //觸發任何綁定的就緒事件 if ( jQuery.fn.trigger ) { jQuery( document ).trigger("ready").off("ready"); } }? 整個過程就是如此。其中有一些小的知識點整理一下。
?
a. 文檔加載狀態document.readyState
document.readyState用來判斷文檔加載狀態,是一個只讀屬性,可能的值有:
0-uninitialized:XML 對象被產生,但沒有任何文件被加載。
1-loading:加載程序進行中,但文件尚未開始解析。
2-loaded:部分的文件已經加載且進行解析,但對象模型尚未生效。
3-interactive:僅對已加載的部分文件有效,在此情況下,對象模型是有效但只讀的。
4-complete:文件已完全加載,代表加載成功。
實例:
document.onreadystatechange = stateChange;//當頁面加載狀態改變的時候執行這個方法. function stateChange() {if(document.readyState == "complete"){ //當頁面加載狀態為完全結束時進入
alert("文檔加載成功")
}
}
但是,老版本的Firefox并不支持document.readyState【最新的Firefox已經支持了】。所以想要兼容所有瀏覽器監聽文檔準備完成分兩種情況來處理:
- 標準瀏覽器使用addEventListener添加DOMContentLoaded和load監聽,任何一個事件被觸發即可
- 老版本IE瀏覽器使用attachEvent添加onreadystatechange和onload來監聽,任何一個被觸發,并且onreadystatechange時document.readyState === "complete"即可。
jQuery的處理也就是如此了
jQuery.ready.promise = function(){...//標準瀏覽器支持DOMContentLoaded事件 else if ( document.addEventListener ) {//綁定DOMContentLoaded事件和響應函數,響應函數會解決延時document.addEventListener( "DOMContentLoaded", completed, false );//回退到window.onload事件綁定,所有的瀏覽器都支持window.addEventListener( "load", completed, false );//如果是IE事件模型} else {//確保在onload之前執行延時,可能時間比較遲,但是對于iframes來說比較安全document.attachEvent( "onreadystatechange", completed );//回退到window.onload事件綁定,所有的瀏覽器都支持window.attachEvent( "onload", completed );
...} } //ready事件處理函數 completed = function( event ) {// readyState === "complete"在老版本IE上適用if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {detach();jQuery.ready();} }
b.doScroll檢測文檔加載完成
這是Diego Perini 發現的一種檢測IE是否加載完成的方式。詳細鏈接
原理是當頁面 DOM 未加載完成時調用 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 );}//移除之前綁定的事件 detach();//執行延遲 jQuery.ready();}})();?
如果覺得本文不錯,請點擊右下方【推薦】!
總結
以上是生活随笔為你收集整理的jQuery-1.9.1源码分析系列(六) 延时对象应用——jQuery.ready的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下的权限问题
- 下一篇: sed 正则表达式【MAC地址】GLPI