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

    1、自定义事件(用户手动trigger的一般都是自定义事件)

    trigger: function( event, data, elem, onlyHandlers ) {

      var i, cur, tmp, bubbleType, ontype, handle, special,

        // 如果没有传入elem(绑定到那个DOM元素上的事件),则默认为document
        eventPath = [ elem || document ],

        // core_hasOwn是hasOwnProperty的替代,检测event上是否有type属性,如果有就将其赋值给type,否则说明event就是type
        type = core_hasOwn.call( event, "type" ) ? event.type : event,

        // 事件的命名空间处理
        namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];

        cur = tmp = elem = elem || document;

      // 如果元素时文本节点或者是注释则直接返回
      if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
        return;
      }

      // 排除替代事件??
      if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
        return;
      } 

      // 如果type中有.号,

      if ( type.indexOf(".") >= 0 ) {
        // 得到自定事件的所有命名空间
        namespaces = type.split(".");

        // 第一个是自定义事件的类型
        type = namespaces.shift();

        // 
        namespaces.sort();
      }

      // 如果type中没有冒号,则为type加上“on”
      ontype = type.indexOf(":") < 0 && "on" + type;

      // 看看有没有jQuery封装后的event对象的标记,如果没有则进行一下改造
      event = event[ jQuery.expando ] ?
        event :
        new jQuery.Event( type, typeof event === "object" && event );

      // 为event对象添加一些额外的属性
      event.isTrigger = onlyHandlers ? 2 : 3;
      event.namespace = namespaces.join(".");
      event.namespace_re = event.namespace ?
        new RegExp( "(^|\.)" + namespaces.join("\.(?:.*\.|)") + "(\.|$)" ) :
        null;

      // 重置event的result属性
      event.result = undefined;

      // 如果event没有target属性,则将elem赋值给它
      if ( !event.target ) {
        event.target = elem;
      }

      // 将传入的data放到数组中,并将event放到数组的第二个元素位置
      data = data == null ?
        [ event ] :
        jQuery.makeArray( data, [ event ] );

      // 看看是不是特殊事件,如果是,用特殊事件的处理方式,并在返回false时返回。
      special = jQuery.event.special[ type ] || {};
      if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
        return;
      }

      // 如果不是onlyHandlers 并且特殊事件不需要冒泡,并且不是window
      if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

        // 如果有替代事件类型,则使用替代事件类型

        bubbleType = special.delegateType || type;

        // 如果不是foucusin和foucusout事件
        if ( !rfocusMorph.test( bubbleType + type ) ) {

          // 则将当前指定为该元素的父元素
          cur = cur.parentNode;
        }

        // 遍历自身及其所有祖先元素,因为自动义事件不会向上冒泡
        for ( ; cur; cur = cur.parentNode ) {

          // 将他们推入eventpath中。
          eventPath.push( cur );
          tmp = cur;
        }

        // 如果最后一个cur是document,则事件触发到window对象上,将window推入队列
        if ( tmp === (elem.ownerDocument || document) ) {
          eventPath.push( tmp.defaultView || tmp.parentWindow || window );
        }
      }

      // 触发该元素上的所有事件处理函数
      i = 0;
      while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {

        event.type = i > 1 ?
          bubbleType :
          special.bindType || type;

        // 拿到对应的event和handle
        handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
        if ( handle ) {

          // 如果有handle就触发
          handle.apply( cur, data );
        }

        // 拿到原始的事件类型
        handle = ontype && cur[ ontype ];

        // 看是否需要阻止默认事件
        if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
          event.preventDefault();
        }
      }  

      // 事件类型可能变了,重新赋值
      event.type = type;

      // 如果不需要阻止默认事件
      if ( !onlyHandlers && !event.isDefaultPrevented() ) {

        if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
          jQuery.acceptData( elem ) ) {

          如果存在原始类型,并且存在事件处理函数,并且不是window
          if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {

            // 元素上的事件赋值给临时变量
            tmp = elem[ ontype ];

            // 清空该元素上的原始事件

            if ( tmp ) {
              elem[ ontype ] = null;
            }

            // 防止再次触发
            jQuery.event.triggered = type;

            // 触发事件处理程序
            elem[ type ]();

            // 清除标记防止再次触发的标记
            jQuery.event.triggered = undefined;

            if ( tmp ) {

              // 再把原始事件写回来
              elem[ ontype ] = tmp;
            }
          }
        }
      }

      // 返回最后一个事件处理程序的返回值

      return event.result;
    },

  • 相关阅读:
    [LeetCode]Remove Duplicates from Sorted Array
    二叉树中和为某一值的路径
    机器学习基石笔记:Homework #2 Decision Stump相关习题
    机器学习基石笔记:08 Noise and Error
    机器学习基石笔记:07 The VC Dimension
    机器学习基石笔记:06 Theory of Generalization
    机器学习基石笔记:05 Training versus Testing
    正交矩阵、EVD、SVD
    win10安装ubuntu16.04及后续配置
    chmod命令相关
  • 原文地址:https://www.cnblogs.com/charling/p/3477700.html
Copyright © 2011-2022 走看看