首頁  >  文章  >  web前端  >  Jquery1.9.1源碼分析系列(六)延時物件應用之jQuery.ready_jquery

Jquery1.9.1源碼分析系列(六)延時物件應用之jQuery.ready_jquery

WBOY
WBOY原創
2016-05-16 15:30:031148瀏覽

還記不記得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();
     }
    })();

以上所述是腳本之家小編給大家介紹的Jquery1.9.1源碼分析系列(六)延時對象應用之jQuery.ready的全部內容,希望大家喜歡。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn