jQuery源码分析之Event事件分析

对于事件的操作无非是addEvent,fireEvent,removeEvent这三个事 件方法。一般lib都会对浏览器的提供的函数做一些扩展,解决兼容性内存泄漏等问题。第三个问题就是如何得到domReady的状态。
  6.1 event的包裹

  浏览器的事件兼容性是一个令人头疼的问题。IE的event在是在全局的window下, 而mozilla的event是事件源参数传入到回调函数中。还有很多的事件处理方式也一样。

  Jquery提供了一个 event的包裹,这个相对于其它的lib提供的有点简单,但是足够使用。

复制代码 代码如下:


//对事件进行包裹。
  fix : function(event) {
    if (event[expando] == true) return event;//表明事件已经包裹过
    //保存原始event,同时clone一个。
    var originalEvent = event;                ①
    event = { originalEvent : originalEvent};
    for (var i = this.props.length, prop;i;) {
       prop = this.props[--i];
      event[prop] = originalEvent[prop];
     }   
    event[expando] = true;   
    //加上preventDefault and stopPropagation,在clone不会运行
    event.preventDefault = function() {          ②
      // 在原始事件上运行
      if (originalEvent.preventDefault)
       originalEvent.preventDefault();
       originalEvent.returnValue = false;
    };
    event.stopPropagation = function() {
      // 在原始事件上运行
      if (originalEvent.stopPropagation)
        originalEvent.stopPropagation();
      originalEvent.cancelBubble = true;
    };
    // 修正 timeStamp
    event.timeStamp = event.timeStamp || now();
    // 修正target
    if (!event.target)                    ③
      event.target = event.srcElement || document;    
    if (event.target.nodeType == 3)//文本节点是父节点。
      event.target = event.target.parentNode;
    // relatedTarget
    if (!event.relatedTarget && event.fromElement)   ④
      event.relatedTarget = event.fromElement == event.target
         ? event.toElement : event.fromElement;
     // Calculate pageX/Y if missing and clientX/Y available
    if (event.pageX == null && event.clientX != null) { ⑥
      var doc = document.documentElement, body = document.body;
     event.pageX = event.clientX
       + (doc && doc.scrollLeft || body && body.scrollLeft || 0)
         - (doc.clientLeft || 0);
      event.pageY = event.clientY
       + (doc && doc.scrollTop || body && body.scrollTop || 0)
         - (doc.clientTop || 0);
    }
  
    // Add which for key events
   if (!event.which && ((event.charCode || event.charCode === 0) ⑦
            ? event.charCode : event.keyCode))
      event.which = event.charCode || event.keyCode;
  
  // Add metaKey to non-Mac browsers
    if (!event.metaKey && event.ctrlKey)            ⑧
      event.metaKey = event.ctrlKey;
   // Add which for click: 1 == left; 2 == middle; 3 == right
  // Note: button is not normalized, so don't use it
    if (!event.which && event.button)             ⑨
      event.which = (event.button & 1 ? 1 : (event.button & 2
         ? 3 : (event.button & 4 ? 2 : 0)));
    return event;
},



  上面的代码①处保留原始事件的引用,同时clone原始事件。在这个clone的事件上进行包裹。②处在原始事件上运行 preventDefault 和 stopPropagation两个方法达到是否阻止默认的事件动作发生和是否停止冒泡事件事件向上传递。

   ③处是修正target个,IE中采用srcElement,同时对于文本节点事件,应该把target传到其父节点。

  ④处 relatedTarget只是对于mouseout、mouseover有用。在IE中分成了to和from两个Target变量,在mozilla中 没有分开。为了保证兼容,采用relatedTarget统一起来。

  ⑥处是进行event的坐标位置。这个是相对于page。如果页面 可以scroll,则要在其client上加上scroll。在IE中还应该减去默认的2px的body的边框。

  ⑦处是把键盘事件的按 键统一到event.which的属性上。Ext中的实现ev.charCode || ev.keyCode || 0; ⑨则是把鼠标事件的按键统一把event.which上。charCode、ev.keyCode一个是字符的按键,一个不是字符的按键。⑨处采 用&的方式来进行兼容性的处理。 Ext 通过下面三行解决兼容问题。

 var btnMap = Ext.isIE ? {1:0,4:1,2:2} : (Ext.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2}); this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);

   ①②③④⑤⑥⑦⑧⑨⑩

  6.2 事件的处理

  Jquery提供了一些来进行regist,remove,fire事件 的方法。

  6.2.1 Register

  对于注册事件,jquery提供了bind、one、toggle、 hover四种注册事件的方法, bind是最基本的方法。One是注册只运行一次的方法,toggle注册交替运行的方法。Hover是注册鼠标浮过的方法。

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdxxjp.html