zoukankan      html  css  js  c++  java
  • jQuery 源码callbacks

    callbacks工具方法,作用是函数回调的统一管理
    
    jQuery.Callbacks = function( options ) {
    		
    }
    
    
    使用:类似于事件绑定,fire之后,之前绑定的方法,都执行。
    观察者模式。
    
    	function aaa()  {
            alert(1);
        }
        function bbb() {
            alert(2);
        }
        function ccc() {
            alert(3)
        }
    
        var cb = $.Callbacks();
        cb.add(aaa);
        cb.add(bbb);
        cb.add(ccc);
    
        cb.fire();		// 弹出了 1 和 2, 3
    
    
        add(fun)-->List添加方法。
        fire对list数组,进行for循环执行。
    
     /**********************************************************/
        function aaa() {
    	    alert(1);
    	}
    
    	(function () {
    
    	    function bbb() {
    	        alert(2);
    	    }
    
    	})();
    
    
    	aaa();
    	bbb();
    	//这里无法同时执行弹出1 和 2,因为无法进行统一作用域的管
    
     /**********************************************************/
    
    
    	// 但是Callbacks可以搞定,这个问题。
    	var cb = $.Callbacks();
    
    	function aaa() {
    	    alert(1);
    	}
    	cb.add(aaa);
    
    	(function () {
    
    	    function bbb() {
    	        alert(2);
    	    }
    
    	    cb.add(bbb);
    
    	})();
    
    	cb.fire();	// 只需要一句就可以了。触发所有
    
    	//这里只要回调对象时全局的, 就可以随时向回调函数中添加函数,而后执行。
    
    
     /**********************************************************/
    
    
    
    jQuery.Callbacks = function( options ) 
    
    
    options配置参数。四个!!!
    
     *	once:			will ensure the callback list can only be fired once (like a Deferred)
     *
     *	memory:			will keep track of previous values and will call any callback added
     *					after the list has been fired right away with the latest "memorized"
     *					values (like a Deferred)
     *
     *	unique:			will ensure a callback can only be added once (no duplicate in the list)
     *
     *	stopOnFalse:	interrupt callings when a callback returns false
    
    Callbacks的四个参数。
    
    var cb = $.Callbacks();
    cb.fire();	
    cb.fire();	//fire可以执行多次触发的。
    
    
    (1)once:代表,fire只能触发一次。
    	cb.fire();	
    	cb.fire();	//不会执行。
    让fire执行一次就好了
    
    (2)memory:
        var cb = $.Callbacks();
        function aaa() {
            alert(1);
        }
        cb.add(aaa);
    
        cb.fire();
    
        function bbb() {
            alert(2);
        }
        cb.add(bbb);
    
       //这段代码执行过后,只能fire出1,不能执行bbb函数
    
    
    	var cb = $.Callbacks('memory');
    	function aaa() {
    	    alert(1);
    	}
    	cb.add(aaa);
    
    	cb.fire();
    
    	function bbb() {
    	    alert(2);
    	}
    	cb.add(bbb);
    
    	//这段代码就是会打印出1 2 。后面的2也可以触发,只要添加就可以执行。
    
    	memory是作用到add上面,然后再调用fire。
    
        var cb = $.Callbacks('memory');
        function aaa() {
            alert(1);
            return false;
        }
        cb.add(aaa);
    
        cb.fire();
    
        function bbb() {
            alert(2);
        }
        
        setTimeout(function () {
             cb.add(bbb);
        }, 1000);
    
    我想了一个例子,应该可以讲的明白,如果变量里面定义了memory,作为初始化,
    那么,就执行。当你调用了fire以后,再向内添加add函数的时候,就直接继续执行。
    					
    
    
    
    (3)unique:去重复,让函数具有唯一性。作用于add
    
    	var cb = $.Callbacks();
    	function aaa() {
    	    alert(1);
    	}
    	cb.add(aaa);
    	cb.add(aaa);
    	cb.fire();
    	//这里触发2次
    
    	var cb = $.Callbacks('unique');
    	function aaa() {
    	    alert(1);
    	}
    	cb.add(aaa);
    	cb.add(aaa);
    	cb.fire();
    	//这里触发1次,重复的函数名,不能放入list,
    
    
    (4)stopOnFalse
    	
    	var cb = $.Callbacks('stopOnFalse');
    	function aaa() {
    	    alert(1);
    	    return false;
    	}
    	cb.add(aaa);
    
    	function bbb() {
    	    alert(2);
    	}
    	cb.add(bbb);
    
    	cb.fire();
    	//这里只是执行了alert(1)。而alert(2),并没有背执行
    	//这个变量作用于fire中,判断函数中是否返回false,如果返回false,就立刻推出list循环。
    
    当然还可以接受到组合的形式,比如,memory和once组合的形式,通过空格来分隔开的。
    
    	var cb = $.Callbacks('once stopOnFalse');
    
    Callbacks方法:
    
    add:			将函数,push入 list 中。
    remove:			删除
    has				检测是否有这个函数,返回false/true
    empty			清空数组
    disable			全部锁住。禁止,不执行。
    lock 			锁住。stack=undefined		
    locked			判断是否锁住
    fireWith
    fire:			--》调用的是fireWith. --》fire = function(data);
    fired  			判断是否fired
    
    
    
    list = [], 用了保存函数列表。
    
    add 添加。
    			add: function() {
    				if ( list ) {
    					// First, we save the current length
    					var start = list.length;
    					(function add( args ) {
    						//这里支持传入多个,cb.add(aaa, bbb);
    						jQuery.each( args, function( _, arg ) {
    							var type = jQuery.type( arg );
    							if ( type === "function" ) {
    								//判断是不是唯一。unique!!!
    								if ( !options.unique || !self.has( arg ) ) {
    									list.push( arg );
    								}
    							} 
    							//支持数组形式, cb.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;
    
    					//有merory就直接执行。
    					} else if ( memory ) {
    						firingStart = start;
    						fire( memory );
    					}
    				}
    				return this;
    			},
    
    支持这个:
    
    cb.add(aaa);
    cb.add(aaa, bbb);
    cb.add([aaa, bbb]);
    
    
    remove:删除。
    对数组进行遍历删除。splice
    
    		remove: function() {
    				if ( list ) {
    					jQuery.each( arguments, function( _, arg ) {
    						var index;
    						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;
    			},
    
    cb.add(aaa);
    cb.add(bbb);
    cb.add(ccc);
    
    cb.remove(bbb);
    cb.fire();		// 就只有aaa 和 ccc
    
    
    fire:执行。
    
    		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; // To prevent further calls using add
    					break;
    				}
    			}
    			firing = false;		//触发结束
    			
    			if ( list ) {		//判断list
    				if ( stack ) {
    					if ( stack.length ) {	//stack的长度部位空,
    					//递归调用
    						fire( stack.shift() );	//将栈中的第一个返回。并且fire
    					}
    				} 
    				//如果有记忆,
    				else if ( memory ) {
    					//列表清空
    					list = [];
    				} else {
    					self.disable();
    				}
    			}
    		},
    
    		//Call all callbacks with the given context and arguments
    		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;
    		},
    
    		// 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;
    		}
    
    
    
    stack = !options.once && [],	//这里定义了一个栈
    
    firing 事件触发的时候。
    		
    
    fireWith:
    		fireWith: function( context, args ) {
    			if ( list && ( !fired || stack ) ) {
    				args = args || [];
    				args = [ context, args.slice ? args.slice() : args ];
    				
    				//这里,如果是firing时,就讲fire压入栈
    				if ( firing ) {	
    					stack.push( args );
    				} else {
    					fire( args );
    				}
    			}
    			return this;
    		},
    
    有个例子
    
    var cb = $.Callbacks();
    
    var singal = true;
    function aaa() {
    	alert(1);
    
    	if (singal) {
    		cb.fire();		//stack.push( args );
    		singal = false;
    	}
    }
    
    cb.add(aaa);
    
    function bbb () {
    	alert(2);
    }
    cb.add(bbb);
    
    cb.fire();
    
    
    弹出顺序是1,2 1,2.
    	这个是在fire中实现的。
    
    			if ( list ) {		//判断list
    				if ( stack ) {
    					if ( stack.length ) {	//stack的长度部位空,
    					//递归调用
    						fire( stack.shift() );	//将栈中的第一个返回。并且fire
    					}
    				} 
    				//如果有memory的时候,就清空数组。
    				else if ( memory ) {
    					//列表清空
    					list = [];
    				} else {
    					self.disable();
    				}
    			}
    
  • 相关阅读:
    毕业设计进度5(2月5日)
    毕业设计进度4(2月4日)
    Intellij IDEA 安装Scala插件 + 创建Scala项目
    中国HBase技术社区第一届Meetup资料大合集
    【大会PPT+直播回顾】HBaseCon亚洲2018峰会
    Java 中的锁原理、锁优化、CAS、AQS 详解!
    Reactor 反应堆设计模式
    IO模型
    浅析Reactor设计模式
    将IDEA工程代码提交到Github
  • 原文地址:https://www.cnblogs.com/hgonlywj/p/4852964.html
Copyright © 2011-2022 走看看