摘要:如果回調(diào)正在進(jìn)行,則修正回調(diào)任務(wù)的長(zhǎng)度為當(dāng)前任務(wù)列表的長(zhǎng)度,以便后續(xù)添加的回調(diào)函數(shù)可以執(zhí)行。
Callback模塊是用來(lái)管理回調(diào)函數(shù),也作為deferred延遲對(duì)象得基礎(chǔ)部分,現(xiàn)在一起來(lái)看看他的源碼。
可選參數(shù):
Options: once: 是否最多執(zhí)行一次, memory: 是否記住最近的上下文和參數(shù) stopOnFalse: 當(dāng)某個(gè)回調(diào)函數(shù)返回false時(shí)中斷執(zhí)行 unique: 相同得回調(diào)只被添加一次
這是可選參數(shù),下面可以進(jìn)行試驗(yàn):
var a = function (value) { console.log("a:" + value); }; var b = function (value) { console.log("b:" + value); }; var callbacks = $.Callbacks(); callbacks.add(a); callbacks.fire(["hello"]); callbacks.add(b); callbacks.fire("中");
下面是他的輸出結(jié)果:
a: hello, a:中, b:中
可以看到得是,當(dāng)我們第二次fire得時(shí)候,a函數(shù)也會(huì)執(zhí)行。
在加入?yún)?shù)進(jìn)行實(shí)驗(yàn),首先加入memory
var callbacks = $.Callbacks({ memory: true }); callbacks.add(a); callbacks.fire("hello"); callbacks.add(b); 輸出: a:hello, b:hello
加入memory參數(shù),memory記錄上一次觸發(fā)回調(diào)函數(shù),之后添加的函數(shù)都用這參數(shù)立即執(zhí)行。在來(lái)看once的使用
var callbacks = $.Callbacks({ once: true }); callbacks.add(a); callbacks.fire("hello"); callbacks.fire("中"); 輸出: a:hello
可以看到的是,雖然執(zhí)行了兩次fire方法,但是只輸出了一次結(jié)果。其他兩個(gè)參數(shù)很好理解,細(xì)節(jié)的部分自己去嘗試。
$.Callbacks = function(options) { options = $.extend({}, options) var memory, fired, firing, firingStart, firingLength, firingIndex, list = [], stack = !options.once && [] }
再看看各個(gè)參數(shù)的意義,memory會(huì)在記憶模式下記住上一次觸發(fā)的上下文和參數(shù),fired代表回調(diào)是否已經(jīng)觸發(fā)過(guò),firing表示回調(diào)正在觸發(fā),firingStart回調(diào)任務(wù)開(kāi)始的位置,firingLength回調(diào)任務(wù)的長(zhǎng)度,firingIndex當(dāng)前回調(diào)的索引,list表示真實(shí)的回調(diào)隊(duì)列,在不是觸發(fā)一次的情況下,用來(lái)緩存觸發(fā)過(guò)程中沒(méi)有執(zhí)行的任務(wù)參數(shù)。
fire = function(data) { memory = options.memory && data fired = true firingIndex = firingStart || 0 firingStart = 0 firingLength = list.length firing = true for ( ; list && firingIndex < firingLength ; ++firingIndex ) { if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) { memory = false break } } firing = false if (list) { if (stack) stack.length && fire(stack.shift()) else if (memory) list.length = 0 else Callbacks.disable() } }
fire函數(shù)是唯一內(nèi)置的函數(shù),他的作用是用于觸發(fā)list的回調(diào)執(zhí)行,首先看看他傳進(jìn)的參數(shù),和咱們?cè)谕獠空{(diào)用$.Callbacks的fire還不太一樣,這里的data是一個(gè)數(shù)組,data[0]表示上下文,data[1]是方法調(diào)用的參數(shù)。然后就是各個(gè)參數(shù)的的初始化,memory表示如果options.memory為true,則保存data,fired為true,如果firingStart為0,那么firingIndex 為0,firingStart置為0,正在觸發(fā)的回調(diào)標(biāo)記firing為true。
然后遍歷回調(diào)列表,逐個(gè)執(zhí)行回調(diào),這個(gè)里邊的if判斷表示的是如果回調(diào)函數(shù)返回的是false并且options.stopOnFalse是false,則清空memory的緩存。遍歷完成后,將執(zhí)行的狀態(tài)改為false。如果list存在,stack也存在,把任務(wù)參數(shù)取出來(lái),調(diào)用fire函數(shù)執(zhí)行。如果memory存在,則清空列表,否則進(jìn)行回調(diào)執(zhí)行
最終這個(gè)文件返回的是Callbacks,我們來(lái)看看他的具體實(shí)現(xiàn):
Callbacks = { add: function () { if (list) { var start = list.length, add = function (args) { $.each(args, funciton(_, arg) { if (typeof arg === "function") { if (!options.unique || !Callbacks.has(arg)) list.push(arg); } else if (arg && arg.length && typeof arg !== "string") add(arg); }) } add(arguments) if (firing) firingLength = list.length; else if (memory) { firingStart = start; fire(memory) } } return this; } }
這個(gè)函數(shù)主要的作用就是像list里邊push回調(diào)。首先判斷l(xiāng)ist是否存在,如果存在,start賦值為list的長(zhǎng)度,在內(nèi)部添加一個(gè)add方法,內(nèi)部add方法主要是向list添加回調(diào),如果我們傳入的參數(shù)是數(shù)組,就再次調(diào)用add方法。然后就是調(diào)用add方法,把a(bǔ)rguments傳進(jìn)去。如果回調(diào)正在進(jìn)行,則修正回調(diào)任務(wù)的長(zhǎng)度f(wàn)iringLength為當(dāng)前任務(wù)列表的長(zhǎng)度,以便后續(xù)添加的回調(diào)函數(shù)可以執(zhí)行。如果memory存在,則把開(kāi)始設(shè)置為新添加列表的第一位,然后調(diào)用fire。
我們?cè)賮?lái)看看fireWith的做法:
fireWith: function(context, args) { if (list && (!fired || stack)) { args = args || []; args = [context, args.slice ? args.slice() : args]; if (firing) stack.push(args); else fire(args); } return this; }
傳入的參數(shù)包括上下文,和參數(shù)列表。函數(shù)執(zhí)行的條件是list存在并且回調(diào)沒(méi)有執(zhí)行或者stack存在,stack可以為空。首先對(duì)args進(jìn)行重新賦值,args[0]是上下文,args[1]是復(fù)制過(guò)來(lái)的列表。如果回調(diào)正在進(jìn)行,向stack里邊添加args,或者就執(zhí)行args。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96640.html
摘要:所以模塊依賴于模塊,在引入前必須引入模塊。原有的方法分析見(jiàn)讀源碼之樣式操作方法首先調(diào)用原有的方法,將元素顯示出來(lái),這是實(shí)現(xiàn)動(dòng)畫(huà)的基本條件。如果沒(méi)有傳遞,或者為值,則表示不需要?jiǎng)赢?huà),調(diào)用原有的方法即可。 fx 模塊提供了 animate 動(dòng)畫(huà)方法,fx_methods 利用 animate 方法,提供一些常用的動(dòng)畫(huà)方法。所以 fx_methods 模塊依賴于 fx 模塊,在引入 fx_m...
摘要:模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā)事件,提交表單。最終返回的結(jié)果是一個(gè)數(shù)組,每個(gè)數(shù)組項(xiàng)為包含和屬性的對(duì)象。否則手動(dòng)綁定事件,如果沒(méi)有阻止瀏覽器的默認(rèn)事件,則在第一個(gè)表單上觸發(fā),提交表單。 Form 模塊處理的是表單提交。表單提交包含兩部分,一部分是格式化表單數(shù)據(jù),另一部分是觸發(fā) submit 事件,提交表單。 讀 Zepto 源碼系列文章已...
摘要:源碼分析一核心代碼分析源碼分析二奇淫技巧總結(jié)本文只分析核心的部分代碼,并且在這部分代碼有刪減,但是不影響代碼的正常運(yùn)行。當(dāng)長(zhǎng)度為則不添加內(nèi)容,否則逐個(gè)將逐個(gè)到當(dāng)前實(shí)例新增直接返回一個(gè)新的構(gòu)造函數(shù)添加初始化方法。 Zepto源碼分析(一)核心代碼分析Zepto源碼分析(二)奇淫技巧總結(jié) 本文只分析核心的部分代碼,并且在這部分代碼有刪減,但是不影響代碼的正常運(yùn)行。 目錄 * 用閉包封裝Z...
摘要:在遍歷的時(shí)候,還對(duì)回調(diào)函數(shù)的返回值進(jìn)行判斷,如果回調(diào)函數(shù)返回,立即中斷遍歷??梢员闅v數(shù)組類數(shù)組或?qū)ο笾械脑?,根?jù)回調(diào)函數(shù)的返回值,將返回值組成一個(gè)新的數(shù)組,并將該數(shù)組扁平化后返回,會(huì)將及排除。 Zepto 提供了豐富的工具函數(shù),下面來(lái)一一解讀。 源碼版本 本文閱讀的源碼為 zepto1.2.0 $.extend $.extend 方法可以用來(lái)擴(kuò)展目標(biāo)對(duì)象的屬性。目標(biāo)對(duì)象的同名屬性會(huì)被...
摘要:調(diào)用來(lái)獲取符合條件的集合元素,這在上篇文章讀源碼之神奇的已經(jīng)有詳細(xì)的論述。然后調(diào)用方法來(lái)合并兩個(gè)集合,用內(nèi)部方法來(lái)過(guò)濾掉重復(fù)的項(xiàng),方法在讀源碼之內(nèi)部方法已經(jīng)有論述。最后也是返回一個(gè)集合。 接下來(lái)幾個(gè)篇章,都會(huì)解讀 zepto 中的跟 dom 相關(guān)的方法,也即源碼 $.fn 對(duì)象中的方法。 讀Zepto源碼系列文章已經(jīng)放到了github上,歡迎star: reading-zepto 源碼...
摘要:不支持事件冒泡帶來(lái)的直接后果是不能進(jìn)行事件委托,所以需要對(duì)和事件進(jìn)行模擬。調(diào)用函數(shù),分隔出參數(shù)的事件名和命名空間。這里判斷是否為函數(shù),即第一種傳參方式,調(diào)用函數(shù)的方法,將上下文對(duì)象作為的第一個(gè)參數(shù),如果存在,則與的參數(shù)合并。 Event 模塊是 Zepto 必備的模塊之一,由于對(duì) Event Api 不太熟,Event 對(duì)象也比較復(fù)雜,所以乍一看 Event 模塊的源碼,有點(diǎn)懵,細(xì)看下...
閱讀 2867·2021-10-21 09:38
閱讀 2764·2021-10-11 10:59
閱讀 3057·2021-09-27 13:36
閱讀 1673·2021-08-23 09:43
閱讀 806·2019-08-29 14:14
閱讀 3044·2019-08-29 12:13
閱讀 3213·2019-08-29 12:13
閱讀 319·2019-08-26 12:24