jQuery1.6.2源码分析(三)事件处理

  针对JQ的源码分析的好的博客已经非常的多了,以下推荐一位哥们的博客:http://nuysoft.iteye.com/blog/1199674

  对于这部分内容,我的这篇博客主要是把一些我自己学习过程中,遇到的一些细节和大家分享以下。

  对于.bind() .one()这些方法来说。他们最终都必须通过jQuery.event.add()方法来绑定事件,而在这个add()方法中,用到的很关键的一句代码就是:

  var elemData = jQuery._data( elem );

  这里用到了JQ缓存方面的知识,不具体讨论,对于这个私有方法_data(elem)来说,首先它传入的就是我们当前触发这个add方法的元素对象(这里要注意,因为live方法也是要调用这个add方法实现的,但live方法都是通过事件委派的原理直接找到根节点,所以这里说的元素对象就不一定是触发live方法的DOM元素了)。我们通过这个方法,找到绑定在这个元素对象上的缓存数据并将这个数据对象赋值给一个变量elemData 。这里最需要注意的就是赋值后的这个变量它是可以直接进行修改的。修改了的结果直接覆盖之前的值,也就是说我如果在别的地方再调用一次jQuery._data(elem) 显示的就是我新修改之后的值。 那么这个数据对象里存储的都是一些什么呢?

  

  这里借用上面分享的博客里的一段代码:

  1.   elemData = {                                                           
  2.     events: {                                                          
  3.         'click' : [                                                    
  4.             { guid: 5, type: 'click', namespace: '', data: undefined,  
  5.                 handle: { guid: 5, prototype: {} }                     
  6.             },                                                         
  7.             { ... }                                                    
  8.         ],                                                             
  9.         'keypress' : [ ... ]                                           
  10.     },                                                                 
  11.     handle: { // DOM事件句柄                                               
  12.         elem: elem,                                                    
  13.         prototype: {}                                                  
  14.     }                                                                  
  15. }
 
  它存储的就是事件类型、事件命名空间、以及事件执行的函数等等。
 
  而我们绑定事件的DOM对象以及一些属性值就存储在一个叫做handleobj的变量里,最终它会被添加到elemData.events.type里。    //type就是'click'、'live'等绑定事件的事件名。
  而jQuery.event.special()方法就是处理一些特殊事件比如live delegate等等,上面存储在缓存里的数据就是用于这些事件。如果是普通的bind()、 one()这些方法,最后它都是执行js原生的绑定事件,但如果是special事件,那么上面的缓存就派上用场了。
  比如live方法。
  首先,根据事件委派的原理,我们绑定事件的对象并不是调用live()方法的dom元素本身,而是它的顶级document 每次我点击dom元素,它都会冒泡到document元素。而我在绑定live方法的时候,已经给document绑定了事件:
 
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
					undefined;
			};
		}

  这段代码是定义了要绑定的事件,我们不探究其原理,知道要绑定的事件就是eventHandle就行了。

  然后通过原生的事件监听函数绑定这个事件给document.

  当冒泡之后触发这个函数时,其调用的就是上面代码里显示的jQuery.event.handle()方法,这个方法里面又调用了一个叫做liveHandler()的方法,在这个方法里 它再一次的调用了之前说道的._data()方法。获取到了我们之前存储的绑定live方法的DOM对象,也就是selector属性里面记录的class id 或者其他参数,通过这个参数,我们再去遍历DOM树获取相应元素。这样就可以确保新添加进来的同ID 或者CLASS 的DOM元素也能绑定上函数,随后将执行函数在这些DOM元素上调用。从而实现了live方法的原理。

 

  

posted @ 2012-03-12 18:19  Krouky  阅读(472)  评论(0编辑  收藏  举报