jQuery 2.0.3 源码分析 事件体系结构
那么jQuery事件处理机制能帮我们处理那些问题?
- 毋容置疑首先要解决浏览器事件兼容问题
- 可以在一个事件类型上添加多个事件处理函数,可以一次添加多个事件类型的事件处理函数
- 提供了常用事件的便捷方法
- 支持自定义事件
- 扩展了组合事件
- 提供了统一的事件封装、绑定、执行、销毁机制
- ……
为了更深入的理解幕后的实现,所以先整理整体的结构思路,从1.7后就去除了live绑定,所以现在的整个事件的API
如图:
jQuery的事件绑定有多个方法可以调用,以click事件来举例:
- click方法
- bind方法
- delegate方法
- on方法
$('#foo').click(function(){ })$('#foo').bind('click',function(){ })$("foo").delegate("td", "click", function() { });$("foo").on("click", "td", function() { });
以上四种绑定都能达到同一样的效果,但是各自又有什么区别,内部又是如何实现?
源码分析
click方式
jQuery.each( ("blur focus focusin focusout load resize scroll unload
click
dblclick " +"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {// Handle event bindingjQuery.fn[ name ] = function( data, fn ) {return arguments.length > 0 ?this.on( name, null, data, fn ) :this.trigger( name );};});
源码很简单,合并15种事件统一增加到jQuery.fn上
内部调用this.on / this.trigger
bind方式
bind: function( types, data, fn ) {return this.on( types, null, data, fn ); }, unbind: function( types, fn ) {return this.off( types, null, fn ); },
同样调用的this.on/this.off
delegate方式
delegate: function( selector, types, data, fn ) {return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) {// ( namespace ) or ( selector, types [, fn] )return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); }
同样调用的this.on/this.off
one方式
one: function( types, selector, data, fn ) {return this.on( types, selector, data, fn, 1 ); },
还是this.on
可见以上的接口只是修改了不同的传递参数,最后都交给on实现的
实现最简单的事件委托
给父元素绑定事件,子元素也能响应
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <!-----------------------------测试代码开始--------------------------------> <div id='p' style="width:500px;height: 500px;background:red"> <div id="test" style="width:50px;height: 50px;background:chartreuse">点击</div> </div> <span id="preserve2b9f1efd3c03447e90ebbff63aeee026" class="wlWriterPreserve"><script> var p = document.getElementById('p'); p.onclick = function(e){ alert(e.target.id) } </script></span> <!-----------------------------测试结束--------------------------------------> </body> </html>
其实委托的原理都是一样的,通过事件对象过滤出关联目标的hack,做相对应的处理,那么JQuery是如何实现的呢?
jQuery事件的流程图
在绑定阶段与执行阶段
那么JQuery为了更好的对事件的支持内部又做了哪些额外的优化操作?
兼容性问题处理:
浏览器的事件兼容性是一个令人头疼的问题。IE的event在是在全局的window下, 而mozilla的event是事件源参数传入到回调函数中。还有很多的事件处理方式也一样
JQuery提供了一个 event的兼容类方案
jQuery.event.fix 对游览器的差异性进行包装处理
例如:
- 事件对象的获取兼容,IE的event在是在全局的window,标准的是event是事件源参数传入到回调函数中
- 目标对象的获取兼容,IE中采用srcElement,标准是target
- relatedTarget只是对于mouseout、mouseover有用。在IE中分成了to和from两个Target变量,在mozilla中 没有分开。为了保证兼容,采用relatedTarget统一起来
- event的坐标位置兼容
- 等等
事件的存储优化:
jQuery并没有将事件处理函数直接绑定到DOM元素上,而是通过$.data存储在缓存$.cahce上,这里就是之前分析的贯穿整个体系的缓存系统了
声明绑定的时候:
- 首先为DOM元素分配一个唯一ID,绑定的事件存储在$.cahce[ 唯一ID ][ $.expand ][ 'events' ]上,而events是个键-值映射对象,键就是事件类型,对应的值就是由事件处理函数组成的数组,最后在DOM元素上绑定(addEventListener/ attachEvent)一个事件处理函数eventHandle,这个过程由 jQuery.event.add 实现。
执行绑定的时候:
- 当事件触发时eventHandle被执行,eventHandle再去$.cache中寻找曾经绑定的事件处理函数并执行,这个过程由 jQuery.event. trigger 和 jQuery.event.handle实现。
- 事件的销毁则由jQuery.event.remove 实现,remove对缓存$.cahce中存储的事件数组进行销毁,当缓存中的事件全部销毁时,调用removeEventListener/ detachEvent销毁绑定在DOM元素上的事件处理函数eventHandle。
事件处理器:
jQuery.event.handlers
针对事件委托和原生事件(例如"click")绑定 区分对待
事件委托从队列头部推入,而普通事件绑定从尾部推入,通过记录delegateCount来划分,委托(delegate)绑定和普通绑定。
其余一些兼容事件的Hooks
fixHooks,keyHooks,mouseHooks
总的来说对于JQuery的事件绑定
在绑定的时候做了包装处理
在执行的时候有过滤器处理
下章就开始深入on内部实现的分析了
jQuery 2.0.3 源码分析 事件体系结构相关推荐
- 菜鸟读jQuery 2.0.3 源码分析系列(1)
原文链接在这里,作为一个菜鸟,我就一边读一边写 jQuery 2.0.3 源码分析系列 前面看着差不多了,看到下面一条(我是真菜鸟),推荐木有入门或者刚刚JS入门摸不着边的看看,大大们手下留情,想一起 ...
- jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)
Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...
- 最细的实现剖析:jQuery 2.0.3源码分析Deferred
Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html **构建Deferred对象时候的流程图** **源码解析** 因为cal ...
- jQuery 2.0.3 源码分析core - 整体架构
拜读一个开源框架,最想学到的就是设计的思想和实现的技巧. 废话不多说,jquery这么多年了分析都写烂了,老早以前就拜读过, 不过这几年都是做移动端,一直御用zepto, 最近抽出点时间把jquery ...
- jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 先来回答博友的提问: 如何解析 div > p + div.aaron input[type="checkb ...
- Pushlet 2.0.3 源码分析
转载地址:http://blog.csdn.net/yxw246/article/details/2418255 Pushlet 2.0.3 源码分析 ----服务器端 1 总体架构 Pushlet从 ...
- Spark2.4.0 SparkEnv 源码分析
Spark2.4.0 SparkEnv 源码分析 更多资源 github: https://github.com/opensourceteams/spark-scala-maven-2.4.0 时序图 ...
- Android 11.0 Settings源码分析 - 主界面加载
Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...
- Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析
相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...
最新文章
- 史上最具体Android集成QQ,微信,微博分享(不用第三方)持续更新中
- 在ubuntu16.04.1配置qemu-img,qemu-nbd
- 【HDU - 1116】【POJ - 1386】Play on Words(判断半欧拉图,欧拉通路)
- 【再认识】认知智能下需要的实体知识与事件知识
- 为什么Python中称__lt__、__gt__等为“富比较”方法
- 《Spring技术内幕(第2版)》PDF 国内经典分析spring源代码
- 字符集与编码(九)——GB2312,GBK,GB18030
- Style后台动态定义[转]
- V-rep学习笔记:机器人逆运动学数值解法(Damped Least Squares / Levenberg-Marquardt Method)...
- Python2.X和Python3.X文件对话框、下拉列表的不同
- 既有禀赋上的自然延展:中国移动咪咕进军元宇宙的底层逻辑
- 扫雷代码(包含扩展函数)
- 盘点世界上千奇百怪的数据中心选址,这些地方你一定想不到!
- EPUB和PDF的区别,有什么好用的epub阅读器
- rtmp 发送h264包,主要是sps,pps,i帧和非i帧
- 当你学会炒菜的时候,你就学会了大数据
- 运用计算机制作多媒体作品,计算机多媒体技术在影视后期制作中的应用
- JMockit Mock 私有方法和私有属性
- 2020delphi还有人用吗?delphi过时了吗?为什么还有那么多程序员坚持继续选择DELPHI作为软件开发工具
- 源码交易平台如何选择