jquery源码分析(七)——事件模块 event(二)
上一章节探讨了事件的一些概念,接下来看下jQuery的事件模块。
jQuery对事件的绑定分别有几个API:.bind()/.live()/.delegate()/.on()/click(),
不管是用什么方式绑定,归根到底还是用addEventListener/attachEvent(IE)处理的,正如jQuery的选择器一样不管如何匹配最终还是使用浏览器提供的几个接口处理。
那么现在就有个疑问,事件为什么还要区分那么多不同的处理方案?
这里就要涉及到之前提到的 DOM 事件处理模型了,捕获与冒泡,传统的事件处理给某一元素绑定了一个点击事件,传入一个回调句柄处理。element.addEventListener('click',doSomething,false),对比传统事件来存在这些问题
第一:大量的事件绑定,性能消耗,而且还需要解绑(IE会泄漏);
第二:绑定的元素必须要存在;
第三: 后期生成HTML会没有事件绑定,需要重新绑定
第四: 语法过于繁杂
针对这些问题,因此jQuery引进是采用委托的机制思想来处理。
谈到事件委托来复习下上节提到的事件模型。DOM 有个事件流的特性,也就是说我们在页面上触发节点的时候事件都会上下或者向上传播,称为事件捕捉和事件冒泡。,DOM2.0 模型将事件处理流程分为三个阶段:事件捕获阶段、事件目标阶段、事件起泡阶段
事件传送可以分为3个阶段。
(1)在事件捕捉(Capturing)阶段,事件将沿着DOM树向下转送,目标节点的每一个祖先节点,直至目标节点。例如,若用户单击了一个超链接,则该单击事件将从document节点转送到html元素,body元素以及包含该链接的p元素。在此过程中,浏览器都会检测针对该事件的捕捉事件监听器,并且运行这件事件监听器。
(2)在目标(target)阶段,浏览器在查找到已经指定给目标事件的事件监听器之后,就会运行该事件监听器。目标节点就是触发事件的 DOM 节点。例如,如果用户单击一个超链接,那么该链接就是目标节点(此时的目标节点实际上是超链接内的文本节点)。
(3)在冒泡(Bubbling)阶段,事件将沿着DOM树向上转送,再次逐个访问目标元素的祖先节点到document节点。该过程中的每一步。浏览器都将检测那些不是捕捉事件监听器的事件监听器,并执行它们。
换句话说,事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document),如.live()
对于jQuery中提供多个api来绑定事件:不管你用的是(click / bind / delegate)之中哪个方法,最终都是 jQuery 底层都是调用 on 方法来完成最终的事件绑定。因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不如直接都采用 on 方法来的痛快和直接使用.on()方法事件处理程序到当前选定的 jQuery 对象中的元素。
在jQuery 1.11中,.on()方法提供绑定事件处理的所有功能、效果不言而喻了,除了性能的差异,通过委托的事件还能很友好的支持动态绑定,只要 on 的delegate 象是 HTML 页面原有的元素,由于是事件的触发是通过Javascript的事件冒泡机制来监测,所以对于所有子元素(包括后期通过JS生成的元素)所有的事件监听均能有效,且由于不用对多个元素进行事件绑定,能够有效的节省内存的损耗。
说了这么多,jQuery提供了这么多绑定的方法,具体有什么区别我们来了解一下:
(1)、.bind()方法:用于直接附加一个事件处理程序到元素上,处理程序附加到 jQuery 对象中当前选中的元素,所以在 .bind() 绑定事件的时候这些元素必须已经存在,很明显就是直接调用没利用委托机制。
(2)、live()方法:将委托的事件处理程序附加到一个页面的 document 元素,从而简化了在页面上动态添加的内容上事件处理的使用。这和delegate() 方法类似,只是把所有事件都委托到document对象上来处理,增加冒泡处理时间。现在已经摒弃该方法了,不推荐使用。还是用例子说明一下:
$('a').live('click', function() { alert("!")})
jQuery 把 alert 函数绑定到 $(document) 元素上,并使用 ’click’和 ’a’作为参数。任何时候只要有事件冒泡到 document 节点上,它就查看该事件是否是一个 click 事件,以及该事件的目标元素与’a’这一CSS 选择器是否匹配,如果都是的话,则执行函数。由于live缺点太多,这里就不一一赘述了。
(3)、 delegate(): 为了突破单一 .bind() 方法的局限性,实现事件委托,引入了.live()方法。后来,为解决“事件传播链”过长的问题,新版本又支持为 .live() 方法指定上下文对象。而为了解决无谓生成元素集合的问题,之后版本干脆直接引入了一个新方法 .delegate()。
使用 .delegate(),前面的例子可以这样写:
$('#element).delegate('a', 'click', function() { alert("!!!") });
jQuery 查找(‘#element’),并将click 事件和’a’这一CSS选择器作为参数把 alert 函数绑定到(‘#element)上。
事件监听原理是:任何时候只要有事件冒泡到$(‘#element)上,它就查看该事件事件类型是否是click事件,以及该事件的目标元素(curTarget)是否与CCS选择器相匹配。如果都满足就执行函数。可以注意到,这一过程与.live()类似,但是其把处理程序绑定到具体的元素而非document这一根上,从而大大减少事件传播过程(事件冒泡过程)。
由此可见.delegate() 方法是一个相对完美的解决方案。但在DOM结构简单的情况下,也可以使用.live()。
(4)、on方法:其实 .bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate()也是一样的都是通过.off()来实现的,该接口只是提供了一种统一绑定事件的方法
总得来说,虽然bind/delegate/live这三个方法都能实现DOM节点事件绑定,但是可以用 .on() 来代替上述的 3 种方法
说了这么多,具体使用过程中该用那个方法呢?
下面来总结一下:
1. 为DOM中的很多元素绑定相同事件;
2. 为DOM中尚不存在的元素绑定事件;
3. 用.bind()的代价是非常大的,它会把相同的一个事件处理程序hook到所有匹配的DOM元素上
4. 不要再用.live()了,它已经不再被推荐了,而且还有许多问题
5. .delegate()会提供很好的方法来提高效率,同时我们可以添加一事件处理方法到动态添加的元素上 实际运用中,事件委托机制(基于事件冒泡)仍存在不足之处:
1. 并非所有的事件都能冒泡,如load, change, submit, focus, blur
2. 加大管理复杂
3. 不好模拟用户触发事件
4. 如何取舍就看项目实际中运用了。
jquery源码分析(七)——事件模块 event(二)的更多相关文章
- jQuery 源码分析(十七) 事件系统模块 实例方法和便捷方法 详解
实例方法和便捷方法是指jQuery可以直接通过链接操作的方法,是通过调用$.event上的方法(上一节介绍的底层方法)来实现的,常用的如下: on(types,selector,data,fn,one ...
- jQuery 源码分析(十一) 队列模块 Queue详解
队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转] jQuery源码分析-如何做jQuery源码分析
jQuery源码分析系列(持续更新) jQuery的源码有些晦涩难懂,本文分享一些我看源码的方法,每一个模块我基本按照这样的顺序去学习. 当我读到难度的书或者源码时,会和<如何阅读一本书> ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
随机推荐
- linux内核中的宏ffs(x)
linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...
- CDOJ 1330 柱爷与远古法阵(高斯消元)
CDOJ 1330 柱爷与远古法阵(高斯消元) 柱爷与远古法阵 Time Limit: 125/125MS (Java/Others) Memory Limit: 240000/240000K ...
- XAML实例教程系列 - 事件(Event) 五
Kevin Fan分享开发经验,记录开发点滴 XAML实例教程系列 - 事件(Event) 2012-06-19 01:36 by jv9, 1727 阅读, 7 评论, 收藏, 编辑 Events, ...
- 【Poj1325】Machine Schedule机器调度
目录 List Description Input Output Sample Input Sample Output HINT Solution Code Position: http://poj. ...
- go语言笔记——是c开发的 lex yacc进行词法和语法分析,go不支持函数和运算符重载,不支持类型继承,也不支持断言,还有泛型
从 Go 1.0.3 版本开始,不再使用 8g,8l 之类的指令进行程序的构建,取而代之的是统一的 go build 和 go install 等命令,而这些指令会自动调用相关的编译器或链接器. 如果 ...
- bzoj4668
并查集+最小生成树 首先我们发现这题可以lct维护最小生成树,但是发现如果生成树在之后是不会修改的,那么就想到了并查集,然后就不知道怎么做了... 其实当我们连接两个连通块的时候,两个连通块只能通过这 ...
- 如何在vue项目中引入阿里巴巴的iconfont图库
1. 打开 http://www.iconfont.cn/ 2. 选择我们喜欢的图标,点击上面的小车,加入图标库,即右侧的购物车 3.点击购物车,点击下载代码 4.解压下载的文件夹,将文件夹复制到 a ...
- MVVMLight消息通知实现机制详解(二)
接上文 MVVMLight消息通知实现机制详解(一) 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型.Key值.Action.Target(订阅对象本身) 在发生订阅事 ...
- html5打开摄像头并用canvas模拟拍照
网上很多关于用HTML5打开本地摄像头的文章,但各有瑕疵.根据我自己的亲身体验,我分享一下我用HTML5打开摄像头的经验. 废话不多说,直接看代码. HTML代码: <video id=&quo ...
- No operations allowed after connection closed--转
https://www.jianshu.com/p/1626d41572f2 Spring boot的单数据源配置比较简单,只需要在application.properties配置相关的jdbc连接的 ...