`
haiyupeter
  • 浏览: 427686 次
  • 性别: 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的东东又断了,现在。

相关推荐

    jQuery1.7中文API

    **jQuery 1.7中文API**是Web开发者的重要参考资料,尤其对于那些偏好使用中文文档的开发者来说,这个离线版的CHM文件提供了全面的jQuery 1.7版本的API指南。CHM(Compiled Help Manual)是一种微软开发的帮助文件...

    jQuery1.7 API + JQuery UI API

    在jQuery 1.7中,`live()`方法被`on()`方法替代,提高了事件处理的性能和灵活性。同时,$.support属性提供了一些浏览器兼容性的检测。 以上只是jQuery 1.7 API和jQuery UI API的部分关键知识点,实际上,这两个库...

    前端常用开发手册-jquery1.7_2代码及jquery1.7_2手册。

    5.2 JSONP跨域:jQuery支持JSONP模式进行跨域请求,只需在URL中加入回调函数名,如`url: "http://example.com?callback=?",`。 5.3 `load()`和`get()`简化:对于简单的数据请求,`load()`用于加载HTML内容,`get()`...

    jquery 手册 1.7 1.8 1.82 版本 方便携带 绿色无毒 解压即可

    《jQuery 手册 1.7 1.8 1.82 版本:全面解析与实战指南》 在Web开发领域,jQuery是一个至关重要的JavaScript库,它极大地简化了DOM操作、事件处理、动画效果以及Ajax交互。这份《jQuery手册 1.7 1.8 1.82 版本》...

    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源码分析(1.7)

    jQuery作为一个轻量级、功能丰富的JavaScript库,在Web开发中扮演着至关重要的角色。它通过提供一系列封装良好的API来简化DOM操作、事件处理、动画效果以及AJAX交互等复杂任务,极大地提高了前端开发效率。 #### 二...

    jQuery 参考手册 速查表

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

    jquery 中英文api

    API文档中的1.6版是jQuery的一个稳定版本,后续有1.7、1.8直至现在的3.x版本,每个版本都有性能优化和新特性的添加。 总的来说,jQuery API中英文版为开发者提供了强大的工具,帮助他们高效地进行前端开发。通过...

    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 1.8.2 速查表

    - `.delegate(selector, "event", function())`:在匹配元素的后代中代理事件处理(jQuery 1.7+)。 - `.undelegate(selector, "event")`:解除后代元素的事件代理(jQuery 1.7+)。 ### 5. **动画** - `.fadeIn()...

    给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 Ajax Error 调试错误的技巧

    本文将深入探讨如何使用jQuery的Ajax错误处理机制进行有效的调试,以及Ajax的相关参数设定,帮助你更好地理解和解决在实际项目中遇到的问题。 首先,当你在使用Ajax进行异步数据获取时,可能会遇到请求失败的情况。...

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

    在使用jQuery UI 1.7版本的dialog组件时,遇到了一个困扰的问题:对话框只能弹出一次。这在进行删除操作时尤为明显,因为通常需要在用户确认后才执行删除动作。原先使用的“确认删除”的方法在这一版本中失效,导致...

    jQuery入门学习代码

    10. **事件代理**:利用`.delegate()`(在jQuery 1.7及以上版本中被`.on()`替代)可以实现事件委托,当动态添加的元素需要绑定事件时特别有用。 学习jQuery的过程中,应注重实践,结合实际项目来理解和运用这些知识...

    jQueryAPI-1.4.1中文

    `.load(url, data, callback)`则可以直接将服务器返回的内容加载到某个元素中。 除此之外,jQuery还支持插件扩展,如`.validate()`用于表单验证,`.datepicker()`生成日期选择器,这些都是jQuery生态的丰富体现。 ...

    超实用的jQuery代码段

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

Global site tag (gtag.js) - Google Analytics