jQuery技术

深入理解jQuery的Event机制(4)

字号+ 作者:H5之家 来源:H5之家 2017-06-20 08:00 我要评论( )

最后是注销事件$.fn.off off: function(types, selector, fn) { var handleObj, type; // 当传递的types是jQuery创建的event对象时 if (types types.preventDefault types.handleObj) { // ( event )dispatched jQu

最后是注销事件$.fn.off


off: function(types, selector, fn) {
var handleObj, type;
// 当传递的types是jQuery创建的event对象时
if (types && types.preventDefault && types.handleObj) {
// ( event )dispatched jQuery.Event
handleObj = types.handleObj;
jQuery(types.delegateTarget).off(
handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
handleObj.selector,
handleObj.handler
);
return this;
}
// 当types是对象,遍历递归
if (typeof types === "object") {
// ( types-object [, selector] )
for (type in types) {
this.off(type, selector, types[type]);
}
return this;
}
if (selector === false || typeof selector === "function") {
// ( types [, fn] )
fn = selector;
selector = undefined;
}
if (fn === false) {
fn = returnFalse;
}
// 统一调用jQuery.event.remove移除事件处理程序及相关信息
return this.each(function() {
jQuery.event.remove(this, types, fn, selector);
});
},

$.fn.off实际上调用的是jQuery.event.remove这个方法:


/**
* 注销元素的事件或者事件集
*
* 通过jQuery.event.remove实现,其执行过程大致如下:
1. 现调用jQuery._data从缓存$.cache中取出elem对应的所有数组(内部数据,与调用jQuery.data存储的数据稍有不同
2. 如果未传入types则移除所有事件句柄,如果types是命名空间,则移除所有与命名空间匹配的事件句柄
3. 如果是多个事件,则分割后遍历
4. 如果未指定删除哪个事件句柄,则删除事件类型对应的全部句柄,或者与命名空间匹配的全部句柄
5. 如果指定了删除某个事件句柄,则删除指定的事件句柄
6. 所有的事件句柄删除,都直接在事件句柄数组jQuery._data( elem ).events[ type ]上调用splice操作
7. 最后检查事件句柄数组的长度,如果为0,或为1但要删除,则移除绑定在elem上DOM事件
8. 最后的最后,如果elem对应的所有事件句柄events都已删除,则从缓存中移走elem的内部数据
9. 在以上的各个过程,都要检查是否有特例需要处理
*/
remove: function(elem, types, handler, selector, mappedTypes) {
var j, handleObj, tmp,
origCount, t, events,
special, handlers, type,
namespaces, origType,
elemData = jQuery.hasData(elem) && jQuery._data(elem);
if (!elemData || !(events = elemData.events)) {
return;
}
types = (types || '').match(core_rnotwhite) || [''];
t = types.length;
while (t--) {
tmp = rtypenamespace.exec(types[t]) || [];
type = origType = tmp[1];
namespaces = (tmp[2] || '').split('.').sort();
// 如果没有指定type,解绑元素的所有事件(包括命名空间上的)
if (!type) {
for (type in events) {
jQuery.event.remove(elem, type + types[t], handler, selector, true);
}
continue;
}
special = jQuery.event.special[type] || {};
type = (selector ? special.delegateType : special.bindType) || type;
// 该事件列表
handlers = events[type] || [];
tmp = tmp[2] && new RegExp("(^|//.)" + namespaces.join("//.(?:.*//.|)") + "(//.|$)");
// 删除匹配的事件
// 事件列表的长度
origCount = j = handlers.length;
while (j--) {
handleObj = handlers[j];
if ((mappedTypes || origType === handleObj.origType) &&
(!handler || handler.guid === handleObj.guid) &&
(!tmp || tmp.test(handleObj.namespace)) &&
(!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) {
// 删除events事件列表中的该项
handlers.splice(j, 1);
// 如果有委托,delegateCount就减一
if (handleObj.selector) {
handlers.delegateCount--;
}
if (special.remove) {
special.remove.call(elem, handleObj);
}
}
}
// 删除通用的事件处理程序,同时避免无限递归
// 如果原始事件列表有项,经过前面的步骤长度为0
if (origCount && !handlers.length) {
if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {
// 删除注册的侦听事件
jQuery.removeEvent(elem, type, elemData.handle);
}
// 删除events[type]属性
delete events[type];
}
}
// 如果events不再使用则删除
if (jQuery.isEmptyObject(events)) {
delete elemData.handle;
// 使用removeData检查空的和清空expando
jQuery._removeData(elem, 'events');
}
},

注销嘛,就是对我们保存在缓存系统中的对应数据进行销毁,这里不赘述了。


总结:


jQuery的event模块非常的强大,我也只是讲了一般流程,它还有一些钩子对象处理浏览器兼容问题,我这里就不探讨了。希望我的讲解可以令你解惑。

第七城市th7cn

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • jQuery 源码系列(八)data 缓存机制

    jQuery 源码系列(八)data 缓存机制

    2017-03-05 11:03

  • 《jQuery技术内幕:深入解析jQuery架构设计与实现原理》(高云)【

    《jQuery技术内幕:深入解析jQuery架构设计与实现原理》(高云)【

    2017-02-05 16:00

  • 《深入PHP与jQuery开发》┊(美) Jason Lengstorf[.PDF] 下载

    《深入PHP与jQuery开发》┊(美) Jason Lengstorf[.PDF] 下载

    2016-12-30 17:07

  • 深入学习jQuery动画控制

    深入学习jQuery动画控制

    2016-11-19 10:01

网友点评