又是一个重磅功能点。
在分析源码之前分析一下体系结构,有助于源码理解。实际上在jQuery出现之前,做的已经比较优秀了;而且jQuery事件系统的设计思想也是基于该思想的,所以我们先分析一下Dean Edwards前辈的事件绑定。
a. jQuery事件原型——Dean Edwards的跨浏览器AddEvent()设计
源码解读
重新梳理一下数据结构,使用一个例子
经过addEvent()函数之后,当前的数据结构为:
事件系统会根据调用addEvent的顺序给每个响应函数(也就是addEvent(element,handler)中的第三个参数handler)打上标记$$guid。源码
f1.$$guid = 1 f2.$$guid = 2 f3.$$guid = 3
而根据源码中
那么某一个函数在任何事件响应函数集合中的下标位置是固定的。比如click和change事件都调用f3作为响应事件,那么f3在element.events.click以及element.events.change中的下标位置都是f3.$$guid = 3;即element.events.click[3] = element.events.change[3] = f3。
这个时候假设又新添了一个事件绑定:addEvent(dom,"focus",f3);那么element.events.focus[3] = f3;这也是对象相比于数组的方便之处,数组不可能没有下标0,1,2就直接有3了,但是对象却可以,此时3是作为对象的一个属性名称。
这样的设计,其实已经具备了jquery事件系统的雏形,包含了几个最主要的特点:
1)element上的所有事件,将保存到element.events属性中,不是直接绑定到element上;这样一个事件可以有无数个响应函数。
2)handleEvent作为element所有事件的“主监听函数”,有它统一管理element上的所有函数。
3)所有浏览器都支持element["on" + type]事件绑定方式,跨浏览器兼容。
好啦,明白了addEvent的事件结构,这个想法确实让人觉得眼前一亮。下面分析jQuery的事件结构
b. jQuery的事件结构
所有的函数添加事件都会进入jQuery.event.add函数。该函数有两个主要功能:添加事件、附加很多事件相关信息。我们直接上源码,源码思想和Dean Edwards的跨浏览器兼容事件添加处理类似。
源码分析
依然用实例来说明jQuery的事件结构
经过添加处理环节,事件添加到了元素上,而且节点对应的缓存数据也添加了相应的数据。结构如下
jQuery的处理和Dean Edwards的跨浏览器兼容事件添加处理类似,比如为每一个函数添加guid;使用events对象存放响应事件列表,有一个总的事件处理入口handle等。
jQuery做了哪些改进?
1)事件数据不再直接保存在节点上,而是使用jQuery缓存系统内(内部使用的缓存jQuery._data方式存取)
2)事件委托:绑定到当前节点(例子中当前节点是document根节点)的处理函数不仅仅包含当前节点触发事件(click)响应时处理的事件(例子中selector为undefined时对应的处理函数dot);还代理了其他节点(例子中的#center节点)触发事件(click)响应时处理的事件(例子中selector为"#center"对应的处理事件doHandler和dot);委托机制在后续分析。
3)增加了很多功能数据,比如命名空间namespace:这个主要用在自定义事件自定义触发,比如$(document).on("chua.click",dot),主动触发$("#center").trigger("chua.click")。还有额外数据data:虽然没有看到那个地方有被用到。
到此jQuery的事件结构就清楚了。后面再分析事件的绑定和触发以及委托原理。
原文链接:https://www.f2er.com/jquery/51621.html