`
haiyupeter
  • 浏览: 418195 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

jQuery1.7中的Callbacks

阅读更多
严格来讲,jQuery的Callback对象只是对于回调的一种封装,使其变得更加通用,机制类似于事件,只是触发是由手工fire触发回调,当然也支持在事件的回调中触发回调列表


// String to Object flags format cache  
var flagsCache = {};  
  
// Convert String-formatted flags into Object-formatted ones and store in cache  
function createFlags( flags ) {  
    var object = flagsCache[ flags ] = {},  
        i, length;  
    flags = flags.split( /\s+/ );  
    for ( i = 0, length = flags.length; i < length; i++ ) {  
        object[ flags[i] ] = true;  
    }  
    return object;  
}  
  
  
/* 
 * 使用以下参数创建一个回调列表: 
 * 
 *  flags:  一个可选的空格间隔的列表,它将改变回调的行为 
 * 
 * 默认情况下,一个回调列表与事件回调动作相同,也可以被触发多次 
 * 
 * 可选的 flags: 
 * 
 *  once:           确保回调列表只能被执行一次 (like a Deferred) 
 * 
 *  memory:         将会保持以前的值,后续添加的回调在最新的内存状态下执行 (like a Deferred) 
 * 
 *  unique:         确保回调只被添加一次 
 * 
 *  stopOnFalse:    当有一个回调返回false时停止  
 * 
 */  
jQuery.Callbacks = function( flags ) {  
  
    // 将 flags 从 String 格式转换成 Object 格式,首先检查全局的 flags   
    flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};  
  
    var // Actual callback list  
        list = [],  
        // Stack of fire calls for repeatable lists  
        stack = [],  
        // 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,  
        // 增加一个或者多个回调到回调列表  
        add = function( args ) {  
            var i,  
                length,  
                elem,  
                type,  
                actual;  
            for ( i = 0, length = args.length; i < length; i++ ) {  
                elem = args[ i ];  
                type = jQuery.type( elem );  
                // 支持添加一个回调列表  
                if ( type === "array" ) {  
                    // Inspect recursively  
                    add( elem );  
                } else if ( type === "function" ) {  
                    // 如果不是在unique模式,或者回调列表中没有当前的回调,则添加  
                    if ( !flags.unique || !self.has( elem ) ) {  
                        list.push( elem );  
                    }  
                }  
            }  
        },  
        // 触发回调列表,fire与add都为内部函数  
        // context参数表示当前的上下文,一般使用document;args,则是向回调函数中传递的参数  
        fire = function( context, args ) {  
            args = args || [];  
            memory = !flags.memory || [ context, args ];  
            fired = true;  
            firing = true;  
            firingIndex = firingStart || 0;  
            firingStart = 0;  
            firingLength = list.length;  
            for ( ; list && firingIndex < firingLength; firingIndex++ ) {  
                //调用回调列表,stopOnFalse 模式下返回为 false 则终止回调  
                if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {  
                    memory = true; // Mark as halted  
                    break;  
                }  
            }  
            firing = false;  
            if ( list ) {  
                // 如果不是只执行一次的,则  
                if ( !flags.once ) {  
                    if ( stack && stack.length ) {  
                        memory = stack.shift();  
                        self.fireWith( memory[ 0 ], memory[ 1 ] );  
                    }  
                } else if ( memory === true ) {  
                    self.disable();  
                } else {  
                    list = [];  
                }  
            }  
        },  
        // 真正的回调对象  
        self = {  
            // 增加一个回调或者回调集合到列表中  
            add: function() {  
                if ( list ) {  
                    var length = list.length;  
                    add( 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, unless previous  
                    // firing was halted (stopOnFalse)  
                    } else if ( memory && memory !== true ) {  
                        firingStart = length;  
                        fire( memory[ 0 ], memory[ 1 ] );  
                    }  
                }  
                return this;  
            },  
            // 从列表中删除一个回调  
            remove: function() {  
                if ( list ) {  
                    var args = arguments,  
                        argIndex = 0,  
                        argLength = args.length;  
                    for ( ; argIndex < argLength ; argIndex++ ) {  
                        for ( var i = 0; i < list.length; i++ ) {  
                            if ( args[ argIndex ] === list[ i ] ) {  
                                // Handle firingIndex and firingLength  
                                if ( firing ) {  
                                    if ( i <= firingLength ) {  
                                        firingLength--;  
                                        if ( i <= firingIndex ) {  
                                            firingIndex--;  
                                        }  
                                    }  
                                }  
                                // Remove the element  
                                list.splice( i--, 1 );  
                                // If we have some unicity property then  
                                // we only need to do this once  
                                if ( flags.unique ) {  
                                    break;  
                                }  
                            }  
                        }  
                    }  
                }  
                return this;  
            },  
            // Control if a given callback is in the list  
            has: function( fn ) {  
                if ( list ) {  
                    var i = 0,  
                        length = list.length;  
                    for ( ; i < length; i++ ) {  
                        if ( fn === list[ i ] ) {  
                            return true;  
                        }  
                    }  
                }  
                return false;  
            },  
            // Remove all callbacks from the list  
            empty: function() {  
                list = [];  
                return this;  
            },  
            // 禁用当前的Callback  
            disable: function() {  
                list = stack = memory = undefined;  
                return this;  
            },  
            // 判断是否已不可用  
            disabled: function() {  
                return !list;  
            },  
            // 锁定当前列表状态  
            lock: function() {  
                stack = undefined;  
                if ( !memory || memory === true ) {  
                    self.disable();  
                }  
                return this;  
            },  
            // 判断是否已经装载  
            locked: function() {  
                return !stack;  
            },  
            // 通过传递context和arguments,调用所有的回调  
            fireWith: function( context, args ) {  
                if ( stack ) {  
                    if ( firing ) {  
                        if ( !flags.once ) {  
                            stack.push( [ context, args ] );  
                        }  
                    } else if ( !( flags.once && memory ) ) {  
                        fire( context, args );  
                    }  
                }  
                return this;  
            },  
            // 通过arguments在当前this上下文下,执行回调列表  
            fire: function() {  
                self.fireWith( this, arguments );  
                return this;  
            },  
            // 判断当前回调列表是否已经被执行过至少一次  
            fired: function() {  
                return !!fired;  
            }  
        };  
  
    return self;  
};  

优点:
1.对线程进行控制,一个回调函数在触发,而另一个又在删除回调的时候,作了标志位的判断
2.对状态进行传递,如果是memory的话,则 参数会进行传递
3.其中使用到jQuery的API只有一个,即 jQuery.type(elem),这个其实是可以改造成标准的javascript的,整个Callback可以抽取成一个插件的形式

将Callback单独抽取了出来,更改了两个地方:
jQuery.Callbacks = function( flags ) {  
    // ...  
}  
  
// 更改为  
  
var Callbacks = function( flags ) {  
    // ...  
};  

type = jQuery.type( elem );  
  
// 更改为:  
  
type = typeof elem; 

// 后续需要对这个作一定的判断,jQuery.type里面写的还是挺完善的 
jQuery.Callbacks 可以在jQuery的官方文档中查看:http://api.jquery.com/jQuery.Callbacks/

附件中带了callbacks.js和它的一个测试案例,callbacks.js完全独立于jQuery.js,所以它是可以用于任何一个项目中的,用于帮助用户抽取回调函数。

后续会写成具有命名空间的插件形式,并不断的完善这个库,暂时将这个库命名为ling.js,有兴趣的朋友也欢迎一起来分析及做适合自己的框架吧!
分享到:
评论
2 楼 haiyupeter 2012-04-01  
晨曦的朝阳 写道
Callbacks确实是个挺好的东西来的,之前我也写了点东东,
http://xiaofei85390656-163-com.iteye.com/admin/blogs/1456889,
写了四篇jquery的东东又断了,现在。


很是不错!
坚持下来吧,对自己会有较大的提高,同时想想看看里面的内容如何整合到自己的项目中去!我现在是在考虑整这些进去的
1 楼 晨曦的朝阳 2012-04-01  
Callbacks确实是个挺好的东西来的,之前我也写了点东东,
http://xiaofei85390656-163-com.iteye.com/admin/blogs/1456889,
写了四篇jquery的东东又断了,现在。

相关推荐

    jQuery中文API

    jquery中文文档api, jQuery 核心函数 jQuery([sel,[context]]) jQuery(html,[ownerDoc]) jQuery(callback) jQuery.holdReady(hold)1.6+ jQuery 对象访问 each(callback) size() length selector context get([index]...

    JQuery新版中文手册

    jQuery(callback) jQuery.holdReady(hold)1.6+ jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData(...

    jQuery 参考手册 速查表

    jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...

    jquery1.11.0手册

    jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...

    jquery插件使用方法大全

    正如Using Deferreds in jQuery 1.5一文中说明的,其结果是在jQuery中能够将依赖于某个任务(事件)结果的逻辑与任务本身解耦了。这一点在JavaScript中其实并不新鲜,Mochikit和Dojo等已经实现有些日子了。由于...

    给jQuery方法添加回调函数一款插件的应用

    插件源码 jquery.callback.js 插件开源地址: ...* @dependency jQuery1.7+ * @author huhai * @since 2013-01-21 */ (function($){ $._callbacks = {}; $._callbacks_ = {}; $._alias = {}; $._alias_ = {}; $.exte

    chm 格式的 jQuery1.11手册

    jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...

    超实用的jQuery代码段

    超实用的jQuery代码段精选近350个jQuery代码段,涵盖页面开发中绝大多数要点、技巧与方法,堪称史上最实用的jQuery代码参考书,可以视为网页设计与网站建设人员的好帮手。《超实用的jQuery代码段》的代码跨平台、跨...

    jQuery ui1.7 dialog只能弹出一次问题

    代码如下:// 显示确认对话框...txtTitle, txtMsg, callback&#41;{ getDivDialog().text(txtMsg).dialog({ modal: true , overlay: { opacity: 0.5 } , title: txtTitle ,buttons: { “是” : function(){ callback(); $

    jprettyCarousel:jQuery轮播插件

    jPrettyCarousel 一个漂亮的轮播插件,可与jQuery 1.7+一起使用版本1.1安装在页面顶部添加插件调用带有可见项数量$("my_container").jprettyCarousel({ visibleItens:5 })的轮播方法设置一些可选参数,可能的参数是...

    jquery-wechat:一个jquery插件,为微信提供方便的工具

    而且这个插件是在jQuery的机制中实现的,这样开发者就不用关心微wechat API的callback不同了。 要求 (1.7+) 安装 bower install -- save jquery - wechat 用法 &lt; script type =" text/javascript " src =" ...

    cxDialog:cxDialog 是基于 jQuery 的对话框插件,支持自定义外观样式,同时兼容 Zepto,方便在移动端使用

    jQuery v1.7+ || Zepto 1.0+ cxDialog v1.2.4 * 兼容 Zepto,需要 支持 文档: 示例: 使用方法 载入 CSS 文件 &lt;link rel="stylesheet" href="jquery.cxdialog.css"&gt; 载入 JavaScript 文件 [removed][removed]...

    jquery.Callbacks的实现详解

    jQuery.Callbacks是jquery在1.7版本之后加入的,是从1.6版中的_Deferred对象中抽离的,主要用来进行函数队列的add、remove、fire、lock等操作,并提供once、memory、unique、stopOnFalse四个option进行一些特殊的...

    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 ...

Global site tag (gtag.js) - Google Analytics