严格来讲,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,有兴趣的朋友也欢迎一起来分析及做适合自己的框架吧!
分享到:
相关推荐
**jQuery 1.7中文API**是Web开发者的重要参考资料,尤其对于那些偏好使用中文文档的开发者来说,这个离线版的CHM文件提供了全面的jQuery 1.7版本的API指南。CHM(Compiled Help Manual)是一种微软开发的帮助文件...
在jQuery 1.7中,`live()`方法被`on()`方法替代,提高了事件处理的性能和灵活性。同时,$.support属性提供了一些浏览器兼容性的检测。 以上只是jQuery 1.7 API和jQuery UI API的部分关键知识点,实际上,这两个库...
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 版本:全面解析与实战指南》 在Web开发领域,jQuery是一个至关重要的JavaScript库,它极大地简化了DOM操作、事件处理、动画效果以及Ajax交互。这份《jQuery手册 1.7 1.8 1.82 版本》...
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(callback) jQuery.holdReady(hold)1.6+ jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData(...
jQuery作为一个轻量级、功能丰富的JavaScript库,在Web开发中扮演着至关重要的角色。它通过提供一系列封装良好的API来简化DOM操作、事件处理、动画效果以及AJAX交互等复杂任务,极大地提高了前端开发效率。 #### 二...
jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...
API文档中的1.6版是jQuery的一个稳定版本,后续有1.7、1.8直至现在的3.x版本,每个版本都有性能优化和新特性的添加。 总的来说,jQuery API中英文版为开发者提供了强大的工具,帮助他们高效地进行前端开发。通过...
jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...
- `.delegate(selector, "event", function())`:在匹配元素的后代中代理事件处理(jQuery 1.7+)。 - `.undelegate(selector, "event")`:解除后代元素的事件代理(jQuery 1.7+)。 ### 5. **动画** - `.fadeIn()...
插件源码 jquery.callback.js 插件开源地址: ...* @dependency jQuery1.7+ * @author huhai * @since 2013-01-21 */ (function($){ $._callbacks = {}; $._callbacks_ = {}; $._alias = {}; $._alias_ = {}; $.exte
jQuery(callback) jQuery.holdReady(hold) jQuery 对象访问 each(callback) size() length selector context get([index]) index([selector|element]) 数据缓存 data([key],[value]) removeData([name|...
本文将深入探讨如何使用jQuery的Ajax错误处理机制进行有效的调试,以及Ajax的相关参数设定,帮助你更好地理解和解决在实际项目中遇到的问题。 首先,当你在使用Ajax进行异步数据获取时,可能会遇到请求失败的情况。...
在使用jQuery UI 1.7版本的dialog组件时,遇到了一个困扰的问题:对话框只能弹出一次。这在进行删除操作时尤为明显,因为通常需要在用户确认后才执行删除动作。原先使用的“确认删除”的方法在这一版本中失效,导致...
10. **事件代理**:利用`.delegate()`(在jQuery 1.7及以上版本中被`.on()`替代)可以实现事件委托,当动态添加的元素需要绑定事件时特别有用。 学习jQuery的过程中,应注重实践,结合实际项目来理解和运用这些知识...
`.load(url, data, callback)`则可以直接将服务器返回的内容加载到某个元素中。 除此之外,jQuery还支持插件扩展,如`.validate()`用于表单验证,`.datepicker()`生成日期选择器,这些都是jQuery生态的丰富体现。 ...
超实用的jQuery代码段精选近350个jQuery代码段,涵盖页面开发中绝大多数要点、技巧与方法,堪称史上最实用的jQuery代码参考书,可以视为网页设计与网站建设人员的好帮手。《超实用的jQuery代码段》的代码跨平台、跨...