jQuery 事件机制源代码分析1——jQuery事件机制整体架构

来源:互联网 发布:mac系统优化工具 编辑:程序博客网 时间:2024/06/05 15:06

之前在网上搜索过一些内容大多都是写的零散写出一些方法感觉不是很系统,要不就是文不对题,后来自己debug 一番大概搞清楚了,决定写个文章记录下来。

需要说明的有以下几点:

1 本文不会教你如何使用.on .off .trigger 等方法 

2  基于源码分析基于自己见解,有错请指出

3 因为整个事件机制过于复杂 计划分几篇写完,

4 本文jQuery 库版本为1.11.2,可以下载 未压缩版对应本文中提到的行数,

5 因单纯的debug 过于枯燥,且易一叶障目,本文计划从以下几个方面来阐述,

     1)jQuery事件机制的整体结构

     2)标准事件绑定

     3)事件命名空间处理

     4)  事件委托处理

     5)自定义事件

     6) 事件对象封装

     7) 事件分发

6 因工作原因本文会陆续更新并修改调整


【jQuery事件机制整体架构】

在讲正文之前,我们可以思考以下几个问题:

     1)标准事件 jQuery 底层是如何进行绑定的?

     2) 自定义事件 jQuery 底层是如何进行绑定

     3) jQuery 绑定的事件如何触发的

     4) 回调函数中Event对象的 data 数据怎么带过去的

     5) 事件委托是如何实现的

在没有分析代码前,我一唯一确定的,标准事件一定是addEventListener / attachEvent ,写这么多废话,带着这些问题可以更有目标性的阅读本文,


【jQuery 事件架构】

从简单开如,通常我们会写下这样类似的代码

$(document).on("click",function(){    alert(1)});

     .on 方法是事件绑定的开始,其实它在背后做了很多看不到的事情,它的做的事情有哪些呢?拿本例来讲

     1) 它会在jQuery.cache 中创建一个对象,这个对象记录了与本次绑定事件相关的一切信息  



问题来了,jQuery.cache  又是什么?见3882行

jQuery.extend({   cache: {},
在jQuery.cache 中创建这个对象有什么用?或者说如何用?后面会讲到,现在先说更重要的事情,但我可以很负责的的告诉你,只要你清掉了jQuery.cache我保证你页面绑定事件绝对会失效(先这样理解),那么很明显,jQuery 不是把回调函数在底层直接绑定,否则只重写,jQuery.cache 怎么可能会让事件绑定失效呢?jQuery 在底层的事件绑定方法确实是,addEventListener / attachEvent  见4378~4384

// Bind the global event handler to the elementif ( elem.addEventListener ) {   elem.addEventListener( type, eventHandle, false );} else if ( elem.attachEvent ) {   elem.attachEvent( "on" + type, eventHandle );}
但它绑定的回调函数是什么呢?见 4326~4336行

if ( !(eventHandle = elemData.handle) ) {   eventHandle = elemData.handle = 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 !== strundefined && (!e || jQuery.event.triggered !== e.type) ?         jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :         undefined;   };   // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events   eventHandle.elem = elem;}
其实无论是document 还是div  或是其它别的东西,它都会用原生JS以这个方法为回调函数,即便清掉jQuery.cache这个回调方法其实还是执行的,只不过没有执行你原始的回调函数而已。

这个方法用网上其它的文章的的说法称为:事件分发器。事件分发器?你讲什么鬼东西,标准事件是系统监听并执行相关回调的,要你来分发什么?答案就是,分发,jQuery.cache !   我们可以认为在此例中,jQuery 为document元素  绑定了一个事件分发器,当相关事件触发时,事件分发器,会去jQuery.cache 中找到与本事件相关的数据对象,并执行相关回调,当然其中还包含一些更复杂的细节,比如委托,全名空间等后面会讲到,这里我们先只说大的架构流程。 

现在有个问题,那就是分发器是如何工作的?它是如何找到document元素相关的cahce 对象呢?或者说,在jQuery.cache 中创建的对象是如何与document 建立映射的?

简单的说,绑定事件时,jQuery 在jQuery.cache 中创建对象的时候,会有一个key ,每个元素只有一个key 且是唯一的,就是上jQuery.cache文图中的 “1”,jQuery 会把这个key  放在document元素自身中,那么这个key 放在哪个属性下呢?

答案就是,

internalKey
我们看代码 3709行

internalKey = jQuery.expando,
再看 2309 行

expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
在控制台敲一下,jQuery.expand 你就会现一个字符串,在事件绑定完成后,我们再在控制台敲一下 document[jQuery.expando]  如图,

这时你似乎明白了些什么吧,我们可以下这样一个结论,只要这个元素用.on绑定了事件(至少有一人没解绑事件),必定它会有这样一个看似奇怪的属性"jQuery111207028145161197981" 这个属性和jQuery.expando相等 是个常量,此元素的这个属性中存放了与jQuery.cache 映射的key 通过这个key 分发器就可以从jQuery.cache 中找到与本元素相关的cache对象。然后经过过滤找到相关的回调函数,并执行。

以上就是大致的一个流程,无论是委托还是直接绑定还是绑定自定义事件,都是这个逻辑,

那么Event 对象的封装又在哪里呢?

Event 对象在事件触发时进行封装,新的jQuery Event 对象会复制原生Event 对象的属性,其它就是消除不同浏览器的差异,比如event.target  event.wich event.relatedTarget 等,添加jQuery Event 对象的一些属性。

事件触发时分发器大概的工作机制上文大概说了一下,具体的细节处理部分后面会分篇进行细写,








0 0
原创粉丝点击