日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jquery源码 DOM加载

發(fā)布時(shí)間:2025/4/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jquery源码 DOM加载 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

jQuery版本:2.0.3

DOM加載有關(guān)的擴(kuò)展

  • isReady:DOM是否加載完(內(nèi)部使用)?
  • readyWait:等待多少文件的計(jì)數(shù)器(內(nèi)部使用)
  • holdReady():推遲DOM觸發(fā)
  • ready():準(zhǔn)備DOM觸發(fā)。
  • jQuery.ready.promise=function(){}; ?監(jiān)聽DOM的異步操作(內(nèi)部使用)

一、$(function(){})和原生window.onload的關(guān)系

這個(gè)在面試中也是經(jīng)常會(huì)被問到的。從下面幾個(gè)角度來分析一下它們的區(qū)別

1、執(zhí)行時(shí)機(jī)

頁面加載,先加載節(jié)點(diǎn),再加載文件,比如img文件,flash等。

$(function(){})DOM加載完執(zhí)行??赡蹹OM元素關(guān)聯(lián)的東西并沒有加載完。

window.onload等節(jié)點(diǎn)和文件都加載完執(zhí)行。

對(duì)應(yīng)的事件監(jiān)聽

jQuery用的是DOMContentLoaded事件。

DOMDContentLoaded:原生DOM加載事件,這個(gè)事件觸發(fā)代表DOM加載完了。

我之前寫過一篇文章的頁面加載時(shí)間分析里也有提到。

onload對(duì)應(yīng)的是load事件。

2、個(gè)數(shù)

window.onload不能寫多個(gè),后面的會(huì)覆蓋前面的。

$(function(){})可以寫多個(gè)。都會(huì)執(zhí)行 。

3、簡化寫法

$(function(){})是$(document)?.ready(function(){});的簡化寫法。

window.onload沒有簡化寫法。

二、jQurey如何實(shí)現(xiàn)DOM ready的

jQuery直接調(diào)用DOMContentLoaded來實(shí)現(xiàn)DOM的ready。但是DOMContentLoaded和onLoad一樣,瀏覽器只執(zhí)行一次,jQuery用什么判斷是否已經(jīng)執(zhí)行過呢?document.readyState就是判斷這個(gè)的依據(jù)。

readyState是document的屬性,總共有3個(gè)值:

  • loading:文檔正在加載中
  • interactive:文檔已經(jīng)加載完成,正在進(jìn)行css和圖片等資源的加載
  • complete:文檔的所以資源加載完成

判斷完之后如何回調(diào)呢?就是用Promise。jQuery通過new一個(gè)$.Deferred(promise)對(duì)象來實(shí)現(xiàn)對(duì)DOM的ready的回調(diào),在DOMContentLoaded中將這個(gè)promise給resolve掉,這樣就執(zhí)行了之前注冊(cè)的回調(diào)函數(shù),同時(shí)后面新注冊(cè)的回調(diào)也會(huì)立刻執(zhí)行。

但是在調(diào)用promise之前,jQuery執(zhí)行了一次setTimeout,因?yàn)閖Query.Promise是不會(huì)產(chǎn)生異步的,這和標(biāo)準(zhǔn)的promise規(guī)范是不一樣的,所有jQuery自己又手動(dòng)做了一次setTimeout來實(shí)現(xiàn)異步。這樣使得無論使用在DOM的ready之前注冊(cè)的回調(diào)還是之后注冊(cè)的回調(diào)都會(huì)在異步中執(zhí)行。

三、源碼整體實(shí)現(xiàn)邏輯

$(fn)==>new一個(gè) jQuery.fn.init(fn)==>返回$(document).ready( fn)。也就是說

  • $(function(){}) =》
  • 調(diào)用$(document).ready(function(){})=》
  • 相當(dāng)于$().ready(fn)實(shí)例方法=》
  • 調(diào)用的jQuery.ready.promise().done(fn)=》
  • jQuery.ready.promise中不管if還是else最終都是調(diào)用jQuery.ready(),并返回promise=》
  • jQuery.ready()里面重點(diǎn)是readyList.resolveWith( document, [ jQuery ] );已完成。至此DOM加載完畢就可以調(diào)用fn了。

?

?

?

四、實(shí)現(xiàn)細(xì)節(jié)

1、重點(diǎn)是:jQuery.ready.promise()方法【巧妙

如果DOM已經(jīng)加載完成了,調(diào)用jQuery.ready()這個(gè)工具方法;

如果DOM沒加載完,監(jiān)聽DOMContentLoaded事件和load事件,等事件發(fā)生時(shí)回調(diào)completed(),最終也是調(diào)用jQuery.ready()這個(gè)工具方法;

var // A central reference to the root jQuery(document) rootjQuery,// The deferred used on DOM ready readyList;jQuery.ready.promise = function( obj ) {if ( !readyList ) { //第一次readyList為空可以進(jìn)來,后續(xù)就進(jìn)不來if了,只執(zhí)行一次 readyList = jQuery.Deferred(); //第一步,創(chuàng)建延遲對(duì)象if ( document.readyState === "complete" ) { //DOM加載完成的標(biāo)志就是document.readyState為complete,如果DOM已經(jīng)加載好了就直接調(diào)工具方法jQuery.ready。setTimeout( jQuery.ready );//加定時(shí)器是為了兼容IE} else {//DOM沒有加載完檢測,即檢測了DOMContentLoaded事件,也檢測了load事件;最終走回調(diào)completed函數(shù)// Use the handy event callbackdocument.addEventListener( "DOMContentLoaded", completed, false );// A fallback to window.onload, that will always workwindow.addEventListener( "load", completed, false ); //因?yàn)榛鸷鼮g覽器會(huì)緩存load事件,為了第一時(shí)間相應(yīng)所以對(duì)load也監(jiān)聽了 }}return readyList.promise( obj ); };

completed回調(diào)函數(shù)如下,最終調(diào)用的也是jQuery.ready()。?

// The ready event handler and self cleanup methodcompleted = function() {//不管是DOMContentLoaded事件還是load發(fā)生,都會(huì)取消2個(gè)事件監(jiān)聽//jQuery.ready()只會(huì)觸發(fā)一次document.removeEventListener( "DOMContentLoaded", completed, false );window.removeEventListener( "load", completed, false );jQuery.ready();};

2、jQuery.ready()工具方法做了些什么?

先做個(gè)測試:

$(function(arg){alert(this); //[object HTMLDocument]alert(arg); //jQuery函數(shù)})

再做個(gè)測試:

除了$(function(){});$(document).ready(function(){}),也可以把ready當(dāng)做事件來處理如下。

<script> $(document).on("ready",function(){alert(123); //123 }); </script>

之所以會(huì)自動(dòng)彈出123,是因?yàn)樵趈Query源碼中用這句話jQuery( document ).trigger("ready").off("ready");來主動(dòng)觸發(fā)了ready事件,觸發(fā)后再取消掉。

// Handle when the DOM is ready ready: function( wait ) { //參數(shù)和holdReady有關(guān)// Abort if there are pending holds or we're already readyif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {return;}// Remember that the DOM is readyjQuery.isReady = true;// If a normal DOM Ready event fired, decrement, and wait if need beif ( wait !== true && --jQuery.readyWait > 0 ) {return;}//第一步看這里重點(diǎn),resolveWith改變狀態(tài)的時(shí)候傳參了,給done中方法fn傳入了參數(shù),//document是fn的this指向,jQuery是參數(shù)// If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] );//跟主動(dòng)觸發(fā)有關(guān)// Trigger any bound ready eventsif ( jQuery.fn.trigger ) {jQuery( document ).trigger("ready").off("ready");} },

跟ready的參數(shù)有關(guān)的有一個(gè)holdReady()。

先做個(gè)測試

$.holdReady(true); $(function () {alert(123); //調(diào)用了holdReady并傳參true,就不能彈出123了 });

可以推遲,也可以釋放推遲,釋放了以后就可以觸發(fā)了。

$.holdReady(true); $.holdReady(false); $(function () {alert(123); //釋放了holdReady,就彈出123 });

這個(gè)有什么用?

比如:

$.getScript('js/a.js',function(){ //異步加載,不會(huì)影響后續(xù)代碼執(zhí)行??赡軙?huì)產(chǎn)生一個(gè)問題,alert(2)先執(zhí)行了a.js還沒有加載完 })$(function () {alert(2);//先彈2,后彈出1 });

很多時(shí)候引入外部文件的時(shí)候,都想等外部文件或者插件加載完,再去觸發(fā)操作,操作可能用到a.js?,F(xiàn)在這個(gè)順序不對(duì),會(huì)出問題。

怎樣解決這個(gè)問題?用holdReady()方法。

$.holdReady(true); //在這里先hold住$.getScript('js/a.js', function () { //異步加載,不會(huì)影響后續(xù)代碼執(zhí)行??赡軙?huì)產(chǎn)生一個(gè)問題,alert(2)先執(zhí)行了a.js還沒有加載完$.holdReady(false); //加載完釋放,不hold了就可以彈2了 })$(function () {alert(2);//先彈2,后彈出1});

再深入一點(diǎn),holdReady() 要針對(duì)的文件可能不止一個(gè),有很多個(gè),所以要等所有的文件都加載完再執(zhí)行,所以源碼中有一個(gè)計(jì)數(shù)的readyWait。

源碼中定義了一個(gè)等待棧變量——readyWait,每次執(zhí)行$.holdReady(true)都會(huì)增加壓棧,而每次$.holdReady()執(zhí)行都會(huì)彈棧,等空棧的時(shí)候就執(zhí)行jQuery.ready函數(shù),即將promise給resolve掉。

// Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1,//第二步看這里 //holdReady推遲DOM的觸發(fā) // Hold (or release) the ready event holdReady: function( hold ) {if ( hold ) {jQuery.readyWait++;//hold為真,讓readyWait加加處理} else {jQuery.ready( true );} },// Handle when the DOM is ready ready: function( wait ) { //參數(shù)和holdReady有關(guān)// Abort if there are pending holds or we're already ready//readyWait為0時(shí)就不用hold了,執(zhí)行后面的操作if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { return;}// Remember that the DOM is readyjQuery.isReady = true; //默認(rèn)是false// If a normal DOM Ready event fired, decrement, and wait if need beif ( wait !== true && --jQuery.readyWait > 0 ) {return;}//第一步看這里重點(diǎn),resolveWith改變狀態(tài)的時(shí)候傳參了,給done中方法fn傳入了參數(shù),//document是fn的this指向,jQuery是參數(shù)// If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] );//跟主動(dòng)觸發(fā)有關(guān)// Trigger any bound ready eventsif ( jQuery.fn.trigger ) {jQuery( document ).trigger("ready").off("ready");} },

?

剛開始看源碼,很多地方理解也不到位,解釋可能也不清楚。

?

參考:

http://www.cnblogs.com/aeexiaoqiang/p/6525702.html

?

本文作者starof,因知識(shí)本身在變化,作者也在不斷學(xué)習(xí)成長,文章內(nèi)容也不定時(shí)更新,為避免誤導(dǎo)讀者,方便追根溯源,請(qǐng)諸位轉(zhuǎn)載注明出處:http://www.cnblogs.com/starof/p/6856572.html有問題歡迎與我討論,共同進(jìn)步。

轉(zhuǎn)載于:https://www.cnblogs.com/starof/p/6856572.html

總結(jié)

以上是生活随笔為你收集整理的jquery源码 DOM加载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。