欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列用法詳解

 更新時(shí)間:2016年06月14日 10:33:14   作者:懶人  
這篇文章主要介紹了jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列用法,結(jié)合實(shí)例形式詳細(xì)分析了jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列的功能、控制標(biāo)志含義與相關(guān)注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了jQuery.Callbacks()回調(diào)函數(shù)隊(duì)列用法。分享給大家供大家參考,具體如下:

1、jQuery.Callbacks

The jQuery.Callbacks() function, introduced in version 1.7, returns a multi-purpose object that provides a powerful way to manage callback lists. It supports adding, removing, firing, and disabling callbacks.

The $.Callbacks() function is internally used to provide the base functionality behind the jQuery $.ajax() and $.Deferred() components. It can be used as a similar base to define functionality for new components.

接下來,我們分別看下四個(gè)標(biāo)準(zhǔn)的控制標(biāo)志。

1.1 once

創(chuàng)建的 callbacks 對象只允許被 fireWith() 一次 [注意:方法fire() 是 fireWith() 的外觀模式]。

var callbacks = $.Callbacks("once");
callbacks.add(function(){console.log("f1");});
callbacks.fire(); //輸出 "f1"
callbacks.fire(); //什么也不發(fā)生,在源碼中已經(jīng)禁用了 list.disable()

1.2 memory

在調(diào)用 add() 方法時(shí),如果這時(shí) callbacks隊(duì)列 滿足 fired && firing = false(真執(zhí)行完畢) && memory(需要在構(gòu)造函數(shù)指定),那么add() 進(jìn)去的回調(diào)函數(shù)會(huì)立即執(zhí)行,而這個(gè) add 進(jìn)去的回調(diào)函數(shù)調(diào)用時(shí)的參數(shù)存儲在 memory 變量中。memory 變量用于存儲最后一次調(diào)用 callbacks.fireWith(...) 時(shí)所使用的參數(shù) [context, arguments]。

If the Callbacks object is created with the "memory" flag as its argument, additional functions may be added and fired after the callback list is locked.

$(function($){
    var callbacks = $.Callbacks("memory");
    callbacks.add(function(){console.log("f1");});
    callbacks.fire(); //輸出 "f1",這時(shí)函數(shù)列表已經(jīng)執(zhí)行完畢!
    callbacks.add(function(){console.log("f2");});  //memory作用在這里,沒有fire,一樣有結(jié)果: f2
    callbacks.fire(); //重新觸發(fā)一次,輸出 f1 f2。 firingStart = 0
    //與once一起使用
    callbacks = $.Callbacks("once memory");
    callbacks.add(function(){console.log("f3");});
    callbacks.fire(); //輸出 "f3",這時(shí)函數(shù)列表已經(jīng)執(zhí)行完畢!
    callbacks.add(function(){console.log("f4");});      //沒有fire,一樣有結(jié)果: f4
    callbacks.fire(); //由于為"once",這里將什么也不執(zhí)行
});

1.3 unique

回調(diào)函數(shù)列表中的函數(shù)是否可以重復(fù),該特性與 add() 方法有關(guān),可以避免在回調(diào)函數(shù)列表中加入多個(gè)相同回調(diào)函數(shù)。

var f1 = function(){console.log("f1");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f1);
callbacks.fire(); //輸出 f1 f1
//傳遞參數(shù) "unique"
callbacks = $.Callbacks("unique");
callbacks.add(f1); //有效
callbacks.add(f1); //添加不進(jìn)去
callbacks.fire(); //輸出: f1

1.4 stopOnFalse

默認(rèn)情況下,當(dāng)執(zhí)行 fireWith() 方法時(shí),整個(gè)回調(diào)函數(shù)列表中的所有函數(shù)都會(huì)順序執(zhí)行,但如果設(shè)置了stopOnFalse,那么當(dāng)某個(gè)函數(shù)返回false時(shí),后邊的函數(shù)將不再執(zhí)行。即使設(shè)置了memory,再次添加的函數(shù)也不會(huì)執(zhí)行了,即一旦某個(gè)函數(shù)返回 false 的情況下,會(huì)禁用 memory 功能。但如果沒設(shè)置”once”,再次調(diào)用fire可以重新觸發(fā)該callbacks。

var f1 = function(){console.log("f1"); return false}; //注意 return false;
var f2 = function(){console.log("f2");};
var callbacks = $.Callbacks();
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //輸出 f1 f2
callbacks = $.Callbacks("memory stopOnFalse");
callbacks.add(f1);
callbacks.add(f2);
callbacks.fire(); //只輸出 f1
callbacks.add(function(){console.log("f3");}); //不會(huì)輸出,memory已經(jīng)失去作用了
callbacks.fire(); //重新觸發(fā),輸出f1

2. memory 回調(diào)隊(duì)列

var i = 0;
var inc = function (s){
 i++;
 alert(i +"$" + s);
};
var callbacks = $.Callbacks('memory');
callbacks.add(function iteral() {
 callbacks.add(inc);
 if (i <= 1) {
  callbacks.fire(i);
 }
});
callbacks.fire(i);
callbacks.add(inc);
/*
list = [];
list = [it];
--->fire(0), i=0
1、list = [it, inc]
2、push(fire(0))
3、i++ [inc(0)] (i=1)
shift()--->fire(0), i=1
1、list = [it, inc, inc];
2、push(fire(1)),
3、i++ [inc(0)]
4、i++ [inc(0)] (i=3)
shift()--->fire(1),i=3
1、list = [it, inc, inc, inc];
2、i++ [inc(1)]
3、i++ [inc(1)]
4、i++ [inc(1)] (i=6)
--->add(inc), i=6, memory=[this,1]
1、i++ [inc(1)] (i=7)
*/

3、 jQuery.CallBacks 源碼

說明:為了便于理解,修改了部分源碼,減少了一些功能~~~

jQuery.Callbacks = function (options) {
  // string --> object 改進(jìn)建議:將未配置的參數(shù)缺省為false,而不是undefined。便于程序閱讀和控制.
  options = optionsCache[options] || createOptions(options);
  var firing,
    memory, //Last fire value [context, args] (for memory lists)
    fired,
    firingLength,
    firingIndex,
    firingStart,
    list = [],
    stack = options.once === true ? false : [], // Stack of fire calls for repeatable lists
    fire = function (data) { // data --> [context, args]
      memory = !!options.memory && data; // false OR [context, arguments]
      fired = true;
      firingIndex = firingStart || 0;
      firingStart = 0;
      firingLength = list.length;
      firing = true;
      // 這里 list 放在條件判斷中是因?yàn)閳?zhí)行回調(diào)函數(shù)可能會(huì)改變 list 的狀態(tài),比如 this.disable()。
      for ( ; list && firingIndex < firingLength; firingIndex++) {
        if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse === true) {
          memory = false; // 禁止 memory 功能,這樣調(diào)用 add() 增加新回調(diào)函數(shù)不會(huì)立即自動(dòng)調(diào)用
          break;
        }
      }
      firing = false;
      if (list) {
        if (stack) {
        //進(jìn)入條件: fired && firing === false && stack, 實(shí)現(xiàn)遞歸調(diào)用
          if (stack.length) {
            fire(stack.shift()); // [[context1, arguments1], [context2, arguments2]]
          }
        } else if (memory) {
        // 進(jìn)入條件: fired && firing === false && stack === undefined && 有memory字段(memory變量只能通過fire()函數(shù)修改)
        // 這里的 list = [],主要是用于性能優(yōu)化,以防該對象長時(shí)間不執(zhí)行,占用系統(tǒng)內(nèi)存
          list = [];
        } else {
        // 進(jìn)入條件: fired && firing === false && stack === undefined && 沒有memory字段, 說明必要繼續(xù)保留的必要
          self.disable();
        }
      }
    },
    self = {
      add: function() {
        if (list) {                  //幾乎所有API都應(yīng)該綁定這個(gè)條件,因?yàn)槲覀冃枰幚黻?duì)列
          var originLength = list.length;
          jQuery.each(arguments, function( _, arg) {
            if (jQuery.type(arg) === "function") {
                // (!(options.unique && self.has(arg))) unique字段的作用
                if (!options.unique || !self.has(arg)) {
                  list.push(arg);
                }
            }
          });
          if (firing === true) {
          // 進(jìn)入條件: 說明正在執(zhí)行回調(diào)函數(shù)隊(duì)列中,而當(dāng)前執(zhí)行的這個(gè)回調(diào)函數(shù)激活了add()函數(shù),及時(shí)維護(hù)循環(huán)邊界
            firingLength = list.length;
          } else if (memory) {
          // 進(jìn)入條件: memory && fired && firing === false, 說明之前的 fire() 行為已經(jīng)完全結(jié)束
            firingStart = originLength;
            fire(memory);
          }
        }
        return this;
      },
      remove: function() {
        if (list) {
          jQuery.each(arguments, function( _, arg) {
            var lastIndex;
            while ((lastIndex = jQuery.inArray(arg, list, lastIndex)) >= 0) {
              list.splice(lastIndex, 1);
              if (firing === true) {         // 及時(shí)更新邊界條件,實(shí)現(xiàn)智能處理
                if (lastIndex <= firingLength) {
                  firingLength--;
                }
                if (lastIndex <= firingIndex) {
                  firingIndex--;
                }
              }
            }
          });
        }
        return this;
      },
      has: function (func) { //這個(gè)API有兩個(gè)功能,根據(jù)單一職責(zé)角度來說,應(yīng)該增加一個(gè) isNotEmpty() 接口(非空)
        return func ? jQuery.inArray(func, list) > -1 : !!(list && list.length);
      },
      empty: function() {
        list = [];
        return this;
      },
      disable: function() { // 徹底禁用該對象, stack禁用, memory禁用
        list = stack = memory = undefined;
        return this;
      },
      disabled: function() {
        return !list;
      },
      lock: function() {
        stack = undefined;
        // 如果memory沒有存儲調(diào)用狀態(tài),直接禁用這個(gè)對象(可能是從未調(diào)用就被鎖定,或者沒有memory字段)
        if (!memory) {
          self.disable();
        }
        return this;
      },
      locked: function() {
        return !stack;
      },
      fireWith: function (context, args) {
        args = args || [];
        var data = [context, args];
        if (list && (fired === false || stack) ) {
          if (firing) {
     // 進(jìn)入條件:  firing === true && stack  說明當(dāng)前正在執(zhí)行回調(diào)函數(shù)隊(duì)列
            stack.push(data);      // stack其實(shí)是一個(gè)隊(duì)列結(jié)構(gòu),這里用 stack 有些混淆
          } else {
     // 進(jìn)入條件一: firing === false && fired === false        說明從來沒有 fire()過
     // 進(jìn)入條件二: firing === false && fired === true && stack = [] 說明至少調(diào)用過一次,而且當(dāng)前允許多次調(diào)用,可以通過lock()鎖定
            fire(args);
          }
        }
        return this;
      },
      fire: function() {
        self.fireWith(this, arguments);
        return this;
      },
      fired: function() {
        return !!fired;
      }
    };
  return self;
};

4、胡思亂想

jQuery.Callbacks() 方法的核心是 fire() 方法,將該 fire() 方法被封裝在函數(shù)中不可直接訪問,因此像 memory、firing、fired 這些狀態(tài)對于外部上下文來說是不可更改的。

還有需要注意的是,如果回調(diào)函數(shù)中使用了 this 對象,可以直接用這個(gè) this 來訪問self對象的公有API。當(dāng)然,也可以用 fireWith() 自己指定 this 的引用對象。

jQuery.Callbacks()的核心思想是 Pub/Sub 模式,建立了程序間的松散耦合和高效通信。

更多關(guān)于jQuery相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《jQuery常用插件及用法總結(jié)》、《jquery中Ajax用法總結(jié)》、《jQuery表格(table)操作技巧匯總》、《jQuery拖拽特效與技巧總結(jié)》、《jQuery擴(kuò)展技巧總結(jié)》、《jQuery常見經(jīng)典特效匯總》、《jQuery動(dòng)畫與特效用法總結(jié)》及《jquery選擇器用法總結(jié)

希望本文所述對大家jQuery程序設(shè)計(jì)有所幫助。

相關(guān)文章

最新評論