美文网首页
JQ第五部分源码学习

JQ第五部分源码学习

作者: 没了提心吊胆的稗子 | 来源:发表于2019-07-21 16:02 被阅读0次

JQ的回调对象处理,通过回调对象管理函数 对函数的统一管理

// 类似于绑定事件
function aa(){
  console.log(1);
}
function bb(){
  console.log(2);
}
var cb = $.Callbacks();
cb.add(aa, bb);
cb.fire();
function aaa() {
  alert(1);
}
cb.add(aaa);
(function () {
  function bbb() {
    alert(2);
    }
    cb.add(bbb);
})();
// 外部直接调用bbb()无法实现
cb.fire(); // 弹出1 2

jQuery.Callbacks = function(options){}中几个参数的作用
once:执行几次cb.fire(),列表里的方法也会执行几次,在定义的时候加上once参数var cb = $.Callbacks('once'),让cb.fire()只能执行一次,可避免cb.fire()多次执行。once是作用到函数列表上的,保证循环的时候只循环一次。
memory:cb.add(aaa); cb.fire(); cb.add(bbb); 按顺序执行的时候由于bbb是后添加的,因此只有aaa被执行了,var cb = $.Callbacks('memory')的作用是添加完方法直接就调用fire来执行这个方法,这时候bbb也会被执行。memory式作用在add方法上的,添加完再作用到fire上。
unique:去重,多次添加同一个函数,会在内部去重,同样是作用在add方法上。
stopOnFalse:如果添加的函数在执行过程中返回值为false,后续添加的函数不会再执行。作用到list循环也就是fire方法上。
四个参数可以组合,用空格分开,例如var cb = $.Callbacks('once memory')

一个函数可以做很多不同的事情,例如判断当前方法在不在list集合里面的时候,若传一个方法进去就用inArray判断在不在,不传的时候就判断这个list有没有

has: function( fn ) {
  return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
}

disable和lock的区别:
disable为阻止后续一切的操作,list,stack,memory都置为undefined
lock是锁住stack,将他置为undefined,而stack是用来控制fire执行次数的,所以lock之后再调用fire就无法执行。

// JQ的回调对象处理,通过回调对象管理函数 对函数的统一管理
jQuery.Callbacks = function( options ) {

    // Convert options from String-formatted to Object-formatted if needed
    // (we check in cache first)
    options = typeof options === "string" ?
        ( optionsCache[ options ] || createOptions( options ) ) :
        jQuery.extend( {}, options );

    var // Last fire value (for non-forgettable lists)
        memory,
        // Flag to know if list was already fired
        fired,
        // Flag to know if list is currently firing
        firing,
        // First callback to fire (used internally by add and fireWith)
        firingStart,
        // End of the loop when firing
        firingLength,
        // Index of currently firing callback (modified by remove if needed)
        firingIndex,
        // Actual callback list
        // 存函数的集合
        list = [],
        // Stack of fire calls for repeatable lists
        stack = !options.once && [],
        // Fire callbacks
        // for循环函数的list集合
        fire = function( data ) {
            memory = options.memory && data;
            fired = true;
            firingIndex = firingStart || 0;
            firingStart = 0;
            firingLength = list.length;
            firing = true;
            for ( ; list && firingIndex < firingLength; firingIndex++ ) {
                // data[1]就是通过fire传的参数
                if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false 
                     && options.stopOnFalse ) {
                    memory = false; // To prevent further calls using add
                    break;
                }
            }
            firing = false;
            if ( list ) {
                if ( stack ) {
                    if ( stack.length ) {
                        fire( stack.shift() );
                    }
                // stack为false 即once为1 只执行一次,完了之后就清空
                } else if ( memory ) {
                    list = [];
                } else {
                    self.disable();
                }
            }
        },
        // Actual Callbacks object
        self = {
            // Add a callback or a collection of callbacks to the list
            add: function() {
                if ( list ) {
                    // First, we save the current length
                    var start = list.length;
                    (function add( args ) {
                        jQuery.each( args, function( _, arg ) {
                            var type = jQuery.type( arg );
                            // 以方法名的形式添加
                            if ( type === "function" ) {
                                if ( !options.unique || !self.has( arg ) ) {
                                    list.push( arg );
                                }
                            // 以数组的形式添加函数 add([aaa, bbb])
                            } else if ( arg && arg.length && type !== "string" ) {
                                // Inspect recursively
                                add( arg );
                            }
                        });
                    })( arguments );
                    // Do we need to add the callbacks to the
                    // current firing batch?
                    if ( firing ) {
                        firingLength = list.length;
                    // With memory, if we're not firing then
                    // we should call right away
                    } else if ( memory ) {
                        firingStart = start;
                        fire( memory );
                    }
                }
                return this;
            },
            // Remove a callback from the list
            remove: function() {
                if ( list ) {
                    jQuery.each( arguments, function( _, arg ) {
                        var index;
                        // 用splice删除当前
                        while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
                            list.splice( index, 1 );
                            // Handle firing indexes
                            if ( firing ) {
                                if ( index <= firingLength ) {
                                    firingLength--;
                                }
                                if ( index <= firingIndex ) {
                                    firingIndex--;
                                }
                            }
                        }
                    });
                }
                return this;
            },
            // Check if a given callback is in the list.
            // If no argument is given, return whether or not list has callbacks attached.
            has: function( fn ) {
                return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
            },
            // Remove all callbacks from the list
            empty: function() {
                list = [];
                firingLength = 0;
                return this;
            },
            // Have the list do nothing anymore
            disable: function() {
                list = stack = memory = undefined;
                return this;
            },
            // Is it disabled?
            disabled: function() {
                return !list;
            },
            // Lock the list in its current state
            lock: function() {
                stack = undefined;
                if ( !memory ) {
                    self.disable();
                }
                return this;
            },
            // Is it locked?
            locked: function() {
                return !stack;
            },
            // Call all callbacks with the given context and arguments
            fireWith: function( context, args ) {
                if ( list && ( !fired || stack ) ) {
                    // fire支持传参 (可以传递给list集合里面的方法)
                    args = args || [];
                    args = [ context, args.slice ? args.slice() : args ];
                    if ( firing ) {
                        stack.push( args );
                    } else {
                        fire( args );
                    }
                }
                return this;
            },
            // Call all the callbacks with the given arguments
            fire: function() {
                self.fireWith( this, arguments );
                return this;
            },
            // To know if the callbacks have already been called at least once
            fired: function() {
                return !!fired;
            }
        };

    return self;
};

相关文章

网友评论

      本文标题:JQ第五部分源码学习

      本文链接:https://www.haomeiwen.com/subject/fenllctx.html