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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

jQuery deferred应用dom加载完毕详细源码分析(三)

發(fā)布時(shí)間:2024/9/5 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jQuery deferred应用dom加载完毕详细源码分析(三) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 我承認(rèn)上章ajax部分寫(xiě)得不好,不要怪我,它的ajax代碼太多了,而且跨越大,方法跳躍多,實(shí)在不好排版與講解,但如果你真正想研究源碼并且仔細(xì)讀了得話,你的

收獲應(yīng)該會(huì)很大,至少你明白了js的ajax是怎么回事.不懂得可以繼續(xù)參閱ajax和Deferred ,其實(shí)我更希望你把deferred搞懂了在看這部分.

? 好吧,言歸正傳,這次我講得是$(function(){console.log("dom ready")}); 多么簡(jiǎn)單的一段代碼,但它是在每個(gè)瀏覽器運(yùn)行的呢?

? 還是先來(lái)個(gè)全局展望,會(huì)用到以下幾個(gè)方法,這里你會(huì)知道jQuery是真正的hold住哥,因?yàn)樗猦old dom ready event holdReady,一個(gè)神奇的方法

? $(fn)?? -->? $.fn.ready(fn)? -->$.bindReady()? --> ? ?? $.ready(wait)???? <--> $.holdReady(hold)

?下面這個(gè)是init函數(shù)的一部分代碼,就是判斷$里面的參數(shù)是函數(shù)

1 // 處理: $(function) 簡(jiǎn)寫(xiě) $(document).ready(function)
2 if (jQuery.isFunction(selector)) {
3 return rootjQuery.ready(selector); ->所以這里你應(yīng)該明白了為什么可以$(fn) 替代$(document).ready(fn)
4 } --> rootjQuery=$(document)

那$(document).ready(fn)后又怎么辦呢? 難道$(document)不是實(shí)例化的一個(gè)jQuery對(duì)象,它當(dāng)然又要去調(diào)用$.fn.ready的函數(shù)

?好,來(lái)到了$.fn.ready,好吧這個(gè)函數(shù)并沒(méi)有管如何處罰dom ready事件,而只是關(guān)心callbacks函數(shù)隊(duì)列fn ,意思就是你$(fn1),$(fn2),

它靠得還是全局的readyList,然后這個(gè)readyList是一個(gè)Deferred對(duì)象,知道它的重要了吧!

1 /*$(fn)--> $(document).ready(fn) 為什么是$(document)而不是其他$("body")呢?
2 * $(function () {console.log(this === document); }); -->true
3 */
4 ready: function (fn) {
5 // Attach the listeners
6 jQuery.bindReady();
7
8 //增加$(fn)里的回調(diào)函數(shù) 以便domready觸發(fā)時(shí)候 readyList.resolveWith(document,[jQuery]); 這里readyList是全局的變量
9 readyList.done(fn);
10
11 return this;
12 },

--->這里可以看到,繼續(xù)去調(diào)用$.bindReady(),這里不關(guān)系dom ready是如何觸發(fā)的

來(lái)到bindReady函數(shù),根據(jù)不同的函數(shù)支持情況進(jìn)行了不同的處理,在這里多少能學(xué)點(diǎn)瀏覽器兼容的知識(shí)了吧,

其實(shí)學(xué)了jQuery,神馬瀏覽器兼容知識(shí)你都學(xué)到了.但是這個(gè)函數(shù)真正關(guān)心得只是事件的添加,不關(guān)心事件如何觸發(fā),,

這里最終的callback觸發(fā)還是交給了$.ready? 這里會(huì)有一個(gè)DOMContentLoaded公用的函數(shù)

1 /* 從這里可以看出來(lái)其實(shí)$(function(){})如果頁(yè)面存在很多的話,也不太會(huì)影響性能,因?yàn)檫@個(gè)$.bindReady只執(zhí)行一次
2 * 而以后$(fn)進(jìn)來(lái)的函數(shù),都通過(guò)deferred的done函數(shù)添加進(jìn)來(lái),只要這個(gè)對(duì)象resolve了,立馬后面所有的fn立即執(zhí)行
3 */
4 bindReady: function () {
5 //如果readyList存在,直接返回,證明這里已經(jīng)創(chuàng)建了一個(gè)deferred對(duì)象
6 if (readyList) {
7 return;
8 }
9 //創(chuàng)建jQuery 私有的deferred
10 readyList = jQuery._Deferred();
11
12 //確保browser event已經(jīng)觸發(fā)過(guò)后,$(document).ready()也將會(huì)被調(diào)用
13 //這個(gè)狀態(tài)表示Fully loaded,document已經(jīng)完全加載了
14 if (document.readyState === "complete") {
-->jQuery代碼總擔(dān)心出錯(cuò),但是你不要擔(dān)心你的回調(diào)會(huì)因?yàn)槎嗵幍谋惶砑拥绞录砑悠髦腥ザ欢啻斡|發(fā)
--> $.ready會(huì)幫你處理的 ~_~
15 // Handle it asynchronously to allow scripts the opportunity to delay ready
16 return setTimeout(jQuery.ready, 1);
17 }
18
19 // Mozilla, Opera and webkit nightlies currently support this event
20 if (document.addEventListener) {
21 //支持DOMContentLoaded事件了,這樣就簡(jiǎn)單了
22 document.addEventListener("DOMContentLoaded", DOMContentLoaded, false);
23
24 // A fallback to window.onload, that will always work ->jQuery代碼總擔(dān)心出錯(cuò),
//但是你不要擔(dān)心,這樣會(huì)不會(huì)多次觸發(fā)你的回調(diào)函數(shù),告訴你當(dāng)然不會(huì)!
25 window.addEventListener("load", jQuery.ready, false);
26
27 // If IE event model is used
28 } else if (document.attachEvent) {
29 //這里主要擔(dān)心頁(yè)面內(nèi)有iframe,所以使用onreadystatechange觸發(fā)
30 document.attachEvent("onreadystatechange", DOMContentLoaded);
31
32 // A fallback to window.onload, that will always work
33 window.attachEvent("onload", jQuery.ready);
34
35 //如果是ie并且頁(yè)面window是toplevel的,繼續(xù)檢查 -> ie關(guān)心的代碼,doScrollCheck()又是神馬呢?
36 //MDN: window.frameElement == null if the window is top-level
37 var toplevel = false;
38
39 try {
40 toplevel = window.frameElement == null;
41 } catch (e) { }
42
43 if (document.documentElement.doScroll && toplevel) {
44 doScrollCheck();
45 }
46 }
47 },

//原來(lái)DOMContentLoaded還是在這里,最后都是交給了$.ready()處理,而DOMContentLoaded并沒(méi)有做什么,只是又一次的去掉事件監(jiān)聽(tīng)
?if (document.addEventListener) {
??????????? DOMContentLoaded = function () {
??????????????? document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
??????????????? jQuery.ready();
??????????? };

??????? } else if (document.attachEvent) {
??????????? DOMContentLoaded = function () {
??????????????? // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
??????????????? if (document.readyState === "complete") {
??????????????????? document.detachEvent("onreadystatechange", DOMContentLoaded);
??????????????????? jQuery.ready();
??????????????? }
??????????? };
??????? }

?/* 這里只針對(duì)ie,當(dāng)頁(yè)面DOM未加載完成時(shí),調(diào)用doScroll方法時(shí),會(huì)產(chǎn)生異常。
? * 那么我們反過(guò)來(lái)用,如果不異常,那么就是頁(yè)面DOM加載完畢了!
? * 這里的想法真的很淫蕩!
? */
??????? function doScrollCheck() {
??????????? if (jQuery.isReady) {
??????????????? return;
??????????? }
??????????? try {
??????????????? // If IE is used, use the trick by Diego Perini
??????????????? // http://javascript.nwbox.com/IEContentLoaded/
??????????????? document.documentElement.doScroll("left");
??????????? } catch (e) {
??????????????? setTimeout(doScrollCheck, 1);
??????????????? return;
??????????? }

??????????? //直到?jīng)]有異常的時(shí)候,執(zhí)行$.ready()
??????????? jQuery.ready();
??????? }
-->你最終會(huì)發(fā)現(xiàn),其實(shí)都是交給了$.ready()處理,不管你怎么觸發(fā)事件 ^_^

?好吧,最后所有的重頭戲都落到了ready,最后的callbacks都是靠他觸發(fā)的,而他里面的readyList又一是一個(gè)deferred對(duì)象,你懂了吧,他要

resolveWith(document,[jQuery]),你知道這個(gè)document意味著什么嗎?$(function(){console.log(this===document)}) ~_~.

1 /* $.holdReady 原來(lái)jQuery才是真正的hold住哥,這里它要hold domReady事件,
2 * $.holdReady(true)--> 延遲hold一次,延遲domReady事件觸發(fā)
3 * $.holdReady(false) --> 釋放hold一次,如果釋放后$.readyWait=0,則觸發(fā)domReady事件
4 * 整個(gè)函數(shù)的功能就是延遲domReady事件,比如你需要?jiǎng)討B(tài)加載一個(gè)jQuery插件神馬的,然后你又要使用這個(gè)插件
5 * $.holdReady(true);$.getScript("myplugin.js", function() { $.holdReady(false);});
6 ->使用上面這個(gè)語(yǔ)句整個(gè)場(chǎng)面都hold住了,加載完成后釋放
7 */
8 holdReady: function (hold) { -->這里你總算看到了神馬是hold住哥
9 if (hold) {
10 jQuery.readyWait++;
11 } else {
12 jQuery.ready(true);
13 }
14 },
15 /*歸根揭底,dom樹(shù)加載完成都是靠它來(lái)觸發(fā)callbacks,只是不同的瀏覽器通過(guò)不同的方式來(lái)觸發(fā)$.ready()
16 */
17 ready: function (wait) {
18 // 釋放hold狀態(tài)或者dom 事件觸發(fā)
19 if ((wait === true && ! --jQuery.readyWait) || (wait !== true && !jQuery.isReady)) {
20 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
21 if (!document.body) {
22 return setTimeout(jQuery.ready, 1);
23 }
24
25 // 表面dom樹(shù)已加載完畢
26 jQuery.isReady = true;
27
28 //if 一個(gè)正常的dom函數(shù)事件觸發(fā)了,但是還有hold的狀態(tài),返回把,先不觸發(fā)
29 if (wait !== true && --jQuery.readyWait > 0) {
30 return;
31 }
32 //觸發(fā)綁定在 readyList.done(fn);中得函數(shù)
33 //函數(shù)原來(lái)還是在這里觸發(fā)的
34 readyList.resolveWith(document, [jQuery]);
35
36 //觸發(fā)任何綁在document ready的事件
37 // $(document).bind({"ready": function () {alert("document ready");} });
38 if (jQuery.fn.trigger) {
39 jQuery(document).trigger("ready").unbind("ready");
40 }
41 }
42 },

?這上面有個(gè)2B的代碼 $(document).bind("ready",function(){..})不知道哪個(gè)2B青年會(huì)用這個(gè)方法...

好吧,如果看懂了上面的代碼,你完全可以寫(xiě)一個(gè)自己的$(function(){}) 而不必為了jQuery為了符合大眾的口味去這樣實(shí)現(xiàn)!



轉(zhuǎn)載于:https://www.cnblogs.com/nothingbrother/archive/2011/12/05/2277369.html

總結(jié)

以上是生活随笔為你收集整理的jQuery deferred应用dom加载完毕详细源码分析(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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