事件处理(二)

通过之前对event.add方法的分析,发现jQuery在事件注册期间,将用户绑定的事件通过jQuery的缓存系统储存在了$.cache中,

jQuery对事件主要做的事情:

1、事件管理

  a、事件注册时,通过add方法,将事件储存在$.cahce[ 唯一ID ][ $.expand ][ 'events' ]上,events内部是“事件类型”:“事件处理函数数组”形式的对象

  b、事件触发时,通过trigger和handler从cache中查找并执行

  c、事件销毁时,通过removie方法从cache中查找并删除

2、浏览器兼容的处理

  a、差异:

    firefox、chrome、oprea、safari、IE9+都支持随事件传入事件处理函数

    IE8-则只能从window对象获取

    event对象内部封装的属性命名有差异,例如keycode、which

  b、统一接口依赖event.fix方法,同时也依赖props、fixHooks、keyHooks、mouseHooks等event的属性

    props中存储原生event对象的通用属性(所有浏览器都相同个)

    keyHook.props 存储键盘事件的特有属性

    mouseHooks.props 存储鼠标事件的特有属性

    // 统一接口(jQuery中用到的event对象是对原event对象的扩展)

    jQuery.Event.prototype = {
      isDefaultPrevented: returnFalse,
      isPropagationStopped: returnFalse,
      isImmediatePropagationStopped: returnFalse,

      preventDefault: function() {
        var e = this.originalEvent;

        this.isDefaultPrevented = returnTrue;

        if ( e && e.preventDefault ) {
          e.preventDefault();
        }
      },
      stopPropagation: function() {
        var e = this.originalEvent;

        this.isPropagationStopped = returnTrue;

        if ( e && e.stopPropagation ) {
          e.stopPropagation();
        }
      },
      stopImmediatePropagation: function() {
        this.isImmediatePropagationStopped = returnTrue;
        this.stopPropagation();
      }
    };

    // 除了上面增加的一些方法,还对其它属性进行了修正

    fix: function( event ) {

      // 如果该event上存在jQuery.expando属性,说明已经是封装过的对象,直接返回该对象
      if ( event[ jQuery.expando ] ) {
        return event;
      }

      var i, prop, copy,
      type = event.type,

      // 将event赋值给originalEvent变量
      originalEvent = event,

      // 到fixHooks中看看有没有对应事件类型的修正
      fixHook = this.fixHooks[ type ];

      // 如果没有,则从mouseHooks或者是keyhooks中取,如果都没有就设置为空对象

      if ( !fixHook ) {
        this.fixHooks[ type ] = fixHook =
          rmouseEvent.test( type ) ? this.mouseHooks :
          rkeyEvent.test( type ) ? this.keyHooks :
          {};
      }

      // 如果有修正后的属性,则和通用的属性连接起来并赋值给copy,否则直接将通用的属性赋值给copy
      copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

      // 创建一个jQuery的event对象

      event = new jQuery.Event( originalEvent );

      i = copy.length;

      // 遍历copy,替换掉原生的一些属性。
      while ( i-- ) {
        prop = copy[ i ];
        event[ prop ] = originalEvent[ prop ];
      }

      // event为什么会没有target
      if ( !event.target ) {
        event.target = document;
      }

      // 呃。。。
      if ( event.target.nodeType === 3 ) {
        event.target = event.target.parentNode;
      }

      return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
    },

原文地址:https://www.cnblogs.com/charling/p/3466240.html