当前位置: 首页 > 编程日记 > 正文

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. 如何取舍就看项目实际中运用了。
 

转载于:https://www.cnblogs.com/hoboStage/p/5014008.html

相关文章:

google gn构建系统的介绍

GN语言和操作 GN语言和操作 内容介绍 使用内置的帮助设计理念语言 字符串清单条件语句循环函数调用作用域和执行Scoping and execution命名事物 文件和目录名称构建配置目标CONFIGS 公共配置模板其他特性 Imports路径处理模式执行脚本与Blaze的区别和相似之处 介绍 本页面描述…

【数据结构】邻接表的储存结构 建立图的邻接表算法

【数据结构】邻接矩阵及其实现 一个图的邻接矩阵的表示是唯一的,但其邻接表表示不唯一,这是因为在邻接表结构中,各便表结点的链接次序取决于建立邻接表时的算法以及输入的次序。 一般而言邻接矩阵适合存储稠密图,邻接表适合存储…

报错:该字符串未被识别为有效的DateTime

报错:该字符串未被识别为有效的DateTime □ 背景 前端的搜索条件中包含关于时间的字符串,由jquery ui的datepicker产生时间字符串。 服务端对时间做了一次转换:DateTime.Parse(Request["时间字段"].ToString())。 搜索的时候没有选…

Nagios监控笔记上

Nagios软件介绍及服务端安装部署实战1. Nagios服务端安装1.1 准备3台服务器或者虚拟机器管理IP地址角色备注192.168.1.80Nagios监控服务器192.168.1.81Lamp服务器被监控的客户端服务器192.168.1.82Lamp服务器被监控的客户端服务器1.2 解决perl编译问题:后面编译的软…

liunx查看python的site-packages路径

有时候我们在liunx上想修改查看python的包路径可以试试以下命令 from distutils.sysconfig import get_python_lib print(get_python_lib()) 如图:

【ACM】杭电OJ 2010

注意格式&#xff01;&#xff01;&#xff01;注意格式&#xff01;&#xff01;&#xff01; 空格的设置 \n的设置 #include <stdio.h> int main () {int i,m,n,g,s,b,flag;while(scanf("%d%d",&m,&n)!EOF){flag0;for(im;i<n;i){gi%10;bi/100…

中科院 工程硕士专业课 复试考试前的辅导安排

同学们大家好&#xff1a;学校定于12月6日、7日组织专业课辅导&#xff0c;1月初进行专业课复试及资格审查。辅导具体日程安排如下&#xff1a;12月6日下午13:00 数据结构&#xff08;报考软件工程、计算机技术领域考生&#xff09; 人文楼教一阶12月7日上午9:00 信号与系统…

TCP性能和发送接收Buffer的关系

本文希望解析清楚&#xff0c;当我们在代码中写下 socket.setSendBufferSize 和 sysctl 看到的rmem/wmem系统参数以及最终我们在TCP常常谈到的接收发送窗口的关系&#xff0c;以及他们怎样影响TCP传输的性能。 先明确一下&#xff1a;文章标题中所说的Buffer指的是sysctl中的 …

PHP 异常类 Exception 高洛峰 细说PHP

/** 1.自定义的异常类&#xff0c;必须是系统类Exception的子类* 如果继承Exception类&#xff0c;重写了构造方法,一定要调用一下父类的构造方法。*/class MyException extends Exception{//必须继承Exception类function __construct($mess){parent::__construct($mess);}func…

【ACM】杭电OJ 2023

注意最后又两个\n #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn 1000; int a[maxn][maxn]; double grade[maxn]; double average[maxn]; int main () {int m,n,i,j,flag,count;//n个学生&#xff0c;m门…

Hadoop学习笔记—7.计数器与自定义计数器

一、Hadoop中的计数器 计数器&#xff1a;计数器是用来记录job的执行进度和状态的。它的作用可以理解为日志。我们通常可以在程序的某个位置插入计数器&#xff0c;用来记录数据或者进度的变化情况&#xff0c;它比日志更便利进行分析。 例如&#xff0c;我们有一个文件&#x…

win10安装spacemacs

1、下载emacs最新版 26.1 2、解压emacs到你的安装目录,我的系统是D:/Program File/。执行/bin目录下的addpm.exe 这一步会在开始菜单创建快捷方式 3、在系统环境变量中添加新项HOME(具体环境变量设置方式请自行google)&#xff0c;该变量的路径决定了emacs启动时.emacs.d目录…

【ACM】杭电OJ 2024

注意&#xff1a; 1、getchar() 2、scanf和gets的区别 3、判断条件 C语言的合法标识符 1、由字母&#xff0c;数字&#xff0c;下划线组成 2、且首字符不能是数字 #include <iostream> #include <cstdio> #include <cstring> using namespace std; in…

王振的开发板_Android

任务一&#xff1a; 任务内容&#xff1a;主界面框架的搭建 发布时间&#xff1a;2016-8-26 已完成 任务二&#xff1a; 任务内容&#xff1a;我的 主界面的开发 发布时间&#xff1a;2016-8-27 已完成 任务三&#xff1a; 任务内容&#xff1a;发布界面 动画开发 发布时间&a…

JAX-RS(基于Jersey) + Spring 4.x + MyBatis构建REST服务架构

0. 大背景 众所周知&#xff0c;REST架构已经成为现代服务端的趋势。 很多公司&#xff0c;已经采用REST作为App, H5以及其它客户端的服务端架构。 1. 什么是JAX-RS? JAX-RS是JAVA EE6 引入的一个新技术。 JAX-RS即Java API for RESTful Web Services&#xff0c;是一个Java 编…

c语言宏嵌套和展开规则

基本原则&#xff1a; 在展开当前宏函数时&#xff0c;如果形参有#或##则不进行宏参数的展开&#xff0c;否则先展开宏参数&#xff0c;再展开当前宏。 #是在定义两边加上双引号 #define _TOSTR(s) #sprintf(_TOSTR(test ABC)) printf(_TOSTR("test ABC")); print…

【ACM】杭电OJ 2027

注意输出格式&#xff01;&#xff01;&#xff01;&#xff01; #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn 10000; char s1[maxn]; int main () {int n,j,i,a,e,o,u;scanf("%d",&n)…

搜索引擎广告过滤Chrome插件

搜索广告屏蔽Chrome插件:自动过滤&#xff1a;百度&#xff0c;360&#xff0c;搜狗&#xff0c;google&#xff0c;bing的搜索广告&#xff0c;让魏则西的悲剧不再重演。珍爱生命&#xff0c;远离搜索广告&#xff01;下载&#xff1a;FuckAd.zip 安装&#xff1a;方法自行百度…

Scala程序设计:Java虚拟机多核编程实战(国内第一本Scala图书)

Scala程序设计&#xff1a;Java虚拟机多核编程实战(国内第一本Scala图书) 基本信息 作者&#xff1a; (美)Venkat Subramaniam 译者&#xff1a; 郑晔 李剑 丛书名&#xff1a; 图灵程序设计丛书 出版社&#xff1a;人民邮电出版社 ISBN&#xff1a;9787115232953 上架时间&am…

emacs快捷键

https://blog.wozouwokan.com/%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91/2015/07/14/spacemacs/ 超全开发快捷键&#xff1a;https://edward852.github.io/post/%E9%80%9A%E7%94%A8%E4%BB%A3%E7%A0%81%E7%BC%96%E8%BE%91%E5%99%A8spacemacs/ spc f T快速定位当前文件在neotree中的…

python 小程序,输错三次密码锁定账户

1 [rootsun ~]# cat 7.py 2 #!/usr/bin/python3 # -*- codingUTF-8 -*-4 5 usera_name usera6 usera_passwd aresu7 usera_status on8 userb_name userb9 userb_passwd bresu 10 userb_status on 11 ng 0 12 13 14 name raw_input(请输入用户名&#xff1a;) 15 …

【数据结构】图的深度优先遍历 广度优先遍历

文件操作比直接输入方便许多 #include <stdio.h> #include <stdlib.h> #include <string.h> #define M 20/*邻接表的储存结构*/ typedef struct node /*表结点 或者 边表结点*/ {int adjvex;struct node *next; }edgenode;typedef struct vnode /*头结点*/ …

C++ Primer(第4版)(评注版)

《C Primer(第4版)(评注版)》基本信息原书名&#xff1a; C Primer (4th Edition) 原出版社&#xff1a; Addison-Wesley Professional; 4 edition 作者&#xff1a; (美)Stanley B.Lippman Josee Lajoie Barbara E.Moo 译者&#xff1a; 陈硕 丛书名&#xff1a; 传世经典书丛…

win10安装emacs+spacemacs,建议用官方安装方式

1、下载emacs最新版 26.1 官网下载地址&#xff1a;https://www.gnu.org/software/emacs/download.html#nonfree 2、解压emacs到你的安装目录,我的系统是D:/Program File/。执行/bin目录下的addpm.exe 这一步会在开始菜单创建快捷方式 3、在系统环境变量中添加新项HOME(具体环…

【ACM】杭电OJ 2028

int 会 WA &#xff0c;注意使用 long long 先除后乘&#xff0c;避免超出范围&#xff0c;但好像本题先乘后除也AC #include <iostream> #include <cstdio> #include <cstring>long long lcm(long long a,long long b) {long long c,t,ma,nb;if(a<b) {…

IIS8 添加配置 WCF服务

今天在Windows8.1 操作系统部署了半天的WCF 一直老是在报错、在这里做个记录 防止下次忘记 在网上查了半天。终于知道原来IIS&#xff18;不支持WCF服务SVC的请求。所以必须要给IIS&#xff18;添加WCF服务 的Managed Handler。 添加步骤&#xff1a; &#xff11;打开IIS&a…

spacemacs各种问题修复方法

快捷键操作时报 tr不是内部命令 ------说明是缺少tr命令&#xff0c;win10可以安装coreutils for gnuwin32工具集&#xff0c;然后把bin目录加到系统path路径即可 没有ispell, flycheck error ------缺少ispell命令&#xff0c;windows下面用aspell替换&#xff0c;需要安装…

2016/08/27 What I Learned About Going Fast at eBay and Google

每天推荐一个英文视频 http://v.qq.com/page/i/2/d/i0...https://www.youtube.com/watch... 本日看点

【ACM】杭电OJ 2030

注意getchar()的使用&#xff0c;以及汉字占两个字节&#xff0c;因为比较特殊&#xff0c;可以单独记忆 #include <iostream> #include <cstdio> #include <cstring> int main () {char c;int n,i,sum;scanf("%d",&n);getchar();while(n--)…

背景图自适应屏幕居中显示,且不变形

html&#xff1a;<div classitem><div class container /> </div> css:.item {width: 100%;height: 100%;.container {max-width: 100%;height: auto;min-height: 600px; // 这里可监听屏幕变化&#xff0c;改变最小高度position: absolute;left: 50%;top:…