1、通过一步步调试的的方法观察了一下存放到cache中的事件及其处理程序的数据格式:

{
  events : { // 根据事件类型存放添加到该元素上的所有事件,下面以click为例
    click : [ // click 事件类型。已数组的形式,按绑定的先后循序存放不同的事件处理函数相关内容(已对象的形式)
      {
        data : "", // 事件绑定时传入的data
                       guid : 1, // jQuery分配的事件的id,用来查找对应的事件,以便删除或进行其它操作
                       namespace : "", // 事件的命名空间
                       needsContext : undefined, // 所需要的环境(暂时不知道是干嘛的)
                       origType : "click", // 原始类型(用户绑定时候的类型,jQuery内部可能会对其进行替换)
                       select : undefined, // 选择器,选择在哪个元素上触发
                       type : "click", // 事件类型
                       handler : function(){} // 用户绑定的事件处理函数。jQuery分类了一个guid作为它的属性
                 }
            ],
            delegateCount : 0 // (暂时不知道是干嘛的)

  },
      handle : function(){} // handle是所有事件类型的触发入口,该方法绑定到了addEventListener的回调上。当事件触发时,首先触发该方法。有一个elem属性
};

2、同时记录了一下jQuery封装之后的event对象中的属性和方法。以click事件对象为例。

event = {
  jQuery121234343 : true, // 标记该事件对象为jQuery封装后的事件对象
  type : "click",
  altkey : false, // 当事件被触发时,alt键是否被按下
  bubbles : true, // 事件是否是起泡事件类型
  button : 0, // 事件触发时,哪个鼠标按钮被按下了
  buttons : 0,
  cancelable : true, // 是否可以取消默认动作
  clientX : 0, // 事件触发时鼠标指针的横坐标
  clientY : 0, // 事件触发时鼠标指针的纵坐标
  ctrlKey : false, // 事件触发时,ctrKey是否被按下
  currentTarget : div(dom), // 触发该事件的元素
  eventPhase : 2, // 事件传播的当前阶段
  metaKey : false, // meta键是否被按下
  offsetX : , // 发生时间的地点在事件触发元素中的横坐标
  offsetY : , // 发生时间的地点在事件触发元素中的纵坐标
  originalEvent : , // 原事件对象
  pageX : , // 距离文档左边缘的鼠标位置
  pageY : , // 距离文档上边缘的鼠标位置
  screenX : , // 以屏幕为基准的鼠标的横坐标
  screenY : , // 以屏幕为基准的鼠标的纵坐标
  shiftKey : , // 当事件触发时,shiftKey是否被按下
  target : div(dom), // 目标元素
  which : , // 按了哪个键或者按钮
  isDefaultPrevented : function(){},
  isImmediatePropagationStopped : function(){},
  isPropagationStopped : function(){},
  preventDefault : function(){},
  stopImmediatePropagation : function(){},
  stopPropagation : function(){}
}

3、通过这几天的读源码和查资料,对事件处理机制已经有了大致的理解,继续梳理一下off、one、trigger的内部逻辑,这三个暴露的接口内部事件是通过 jQuery.event的remove、add和trigger实现的。加下来重点看下remove。(trigger的事件方法和通过事件监听触发思路基本一致,源码不再分析)

  remove: function( elem, types, handler, selector, mappedTypes ) {   
    var j, origCount, tmp,
      events, t, handleObj,
      special, handlers, type, namespaces, origType,

      // 取出存放在cache中的该元素相关的所有事件及事件相关信息
      elemData = data_priv.hasData( elem ) && data_priv.get( elem );
    // 如果不存在,或者没有events属性,说明没有绑定任何事件,直接返回
    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 ];

      // 如果类型一致、id一致、在命名空间内、选择器(事件触发的元素)一致,则删除该项
                if ( ( mappedTypes || origType === handleObj.origType ) &&
                    ( !handler || handler.guid === handleObj.guid ) &&
                    ( !tmp || tmp.test( handleObj.namespace ) ) &&
                    ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
                       handlers.splice( j, 1 );
         // 如果被删除的这一项有selector,说明使用了事件代理,将事件代理的数量减一
                      if ( handleObj.selector ) {
                          handlers.delegateCount--;
                      }

         // 对特殊事件的处理
                      if ( special.remove ) {
                          special.remove.call( elem, handleObj );
                      }
                  }
      }

      // 一些特殊处理(暂不理解)
              if ( origCount && !handlers.length ) {
                  if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
                      jQuery.removeEvent( elem, type, elemData.handle );
                  }

    delete events[ type ];
              }
          }

     // 如果事件全部被清除了,则同时也删掉事件回调的入口和事件存放的容器
          if ( jQuery.isEmptyObject( events ) ) {
              delete elemData.handle;
              data_priv.remove( elem, "events" );
          }
      },

jQuery事件处理(六)的更多相关文章

  1. [DOM Event Learning] Section 3 jQuery事件处理基础 on(), off()和one()方法使用

    [DOM Event Learning] Section 3 jQuery事件处理基础 on(),off()和one()方法使用   jQuery提供了简单的方法来向选择器(对应页面上的元素)绑定事件 ...

  2. jQuery事件处理了解一下

    >>> JQuery 事件处理 一.事件绑定方式 1.事件绑定的快捷方式: 缺点:绑定的事件,无法取消 $("button:eq(0)").dblclick(fu ...

  3. jQuery事件处理(四)

    看了几天,决定整理一下jQuery事件处理的整体设计思路 1.通过add方法给选中的元素注册事件处理程序(通过缓存系统将事件储存到cache,而不是绑定到元素上) a.在存储之前,会为事件处理程序增加 ...

  4. Unit02: jQuery事件处理 、 jQuery动画

    Unit02: jQuery事件处理 . jQuery动画 jQuery实现购物车案例 <!DOCTYPE html> <html> <head> <titl ...

  5. JQuery事件处理的注意事项

    1.jQuery 名称冲突 jQuery 使用 $ 符号作为 jQuery 的简介方式. 某些其他 JavaScript 库中的函数(比如 Prototype)同样使用 $ 符号. jQuery 使用 ...

  6. jQuery第六章

    jQuery与Ajax应用 一.Ajax的优势和不足 1.Ajax的优势: (1)不需要插件支持:不需要任何浏览器插件就可以被绝大多数浏览器支持 (2)优秀的用户体验:能在不刷新整个页面的前提下更新数 ...

  7. 02-老马jQuery教程-jQuery事件处理

    1. 绑定简单事件 在DOM中DOM0级绑定事件的方式是直接给事件属性赋值,但是这样有个缺点就是每次指定的事件处理程序会把之前的覆盖掉. jQuery简单绑定事件的方式,可以让我绑定多个事件处理程序跟 ...

  8. jQuery事件处理(七)

    1.自定义事件(用户手动trigger的一般都是自定义事件) trigger: function( event, data, elem, onlyHandlers ) { var i, cur, tm ...

  9. jQuery事件处理(五)

    对原生js不熟悉看jQuery会困难很多.后续需要更多的关注下原生js jQuery封装之后的事件触发,其中一个分支(处理普通事件)是通过:elem.addEventListener( type, e ...

随机推荐

  1. [poj 1947] Rebuilding Roads 树形DP

    Rebuilding Roads Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 10653 Accepted: 4884 Des ...

  2. 谈谈如何优化MYSQL数据库查询

    1.优化数据类型 MySQL中数据类型有多种,如果你是一名DBA,正在按照优化的原则对数据类型进行严格的检查,但开发人员可能会选择他们认为最简单的方案,以加快编码速度,或者选择最明显的选择,因此,你可 ...

  3. 机器学习——利用PCA来简化数据

    降维技术的好处: 1.使得数据集更易使用 2.降低很多算法的计算开销 3.取出噪声 4.使得结果易懂 在已标注和未标注的数据上都有降维技术,降维的方法: 1.主成分分析(Principal Compo ...

  4. Linux学习笔记(一):文件操作命令

    命令 含义 cd / 切换到根目录 cd .. 上级目录 cd ./bin 到同级的bin目录中 cd bin 到同级的bin目录中 cd - usr文件夹 cd ~ 回到root用户的主文件夹 pw ...

  5. 利用neon技术对矩阵旋转进行加速(2)

    上次介绍的是顺时针旋转90度,最近用到了180度和270度,在这里记录一下. 1.利用neon技术将矩阵顺时针旋转180度: 顺时针旋转180度比顺时针旋转90度容易很多,如下图 A1 A2 A3 A ...

  6. 装饰模式(Decorator Pattern)--------结构型模式

    装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为.装饰模式降低类系统的耦合度,可以动态地增加或删除对象的职责,并使得需要装饰的具体构件类和具体装饰类可以独立变化,以便增加新的具体构件 ...

  7. Android学习之——实现圆角Button

    在drawable文件夹下新建btn_shape.xml文件: <?xml version="1.0" encoding="utf-8"?> < ...

  8. Android学习笔记——log无法输出的解决方法和命令行查看log日志

    本人邮箱:JohnTsai.Work@gmail.com,欢迎交流讨论. 欢迎转载,转载请注明网址:http://www.cnblogs.com/JohnTsai/p/3983936.html. 知识 ...

  9. [Module] 08 - MVP by Mosby

    From: Mosby MVP使用教程[作者用心] View是消极视图(Passive View), 它尽量不去主动做事, 让Presenter通过抽象方式控制View 例子: 例如Presenter ...

  10. 在oracle配置mysql数据库的dblink

    本文介绍如何在oracle配置mysql数据库的dblink:虽然dblink使用很占资源:俗称“性能杀手”.但有些场景不得不使用它.例如公司使用数据库是oracle:可能其他部门或者CP合作公司使用 ...