zoukankan      html  css  js  c++  java
  • jQuery事件处理(六)

    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" );
              }
          },

  • 相关阅读:
    DGA域名可以是色情网站域名
    使用cloudflare加速你的网站隐藏你的网站IP
    167. Two Sum II
    leetcode 563. Binary Tree Tilt
    python 多线程
    leetcode 404. Sum of Left Leaves
    leetcode 100. Same Tree
    leetcode 383. Ransom Note
    leetcode 122. Best Time to Buy and Sell Stock II
    天津Uber优步司机奖励政策(12月28日到12月29日)
  • 原文地址:https://www.cnblogs.com/charling/p/3475880.html
Copyright © 2011-2022 走看看