我们试图绑定一些事件到DOM元素上的时候,我相信上面这4个方法是最常用的。而它们之间到底有什么不同呢?在什么场合下用什么方法是最有效的呢?
1.准备知识
当我们在开始的时候,有些知识是必须具备的:
1).DOM树
下图仅仅是一个示例,这是一个在browser环境下的一棵模拟DOM树,在下面的代码中仅起到演示的作用:
2).Event bubbling (aka event propagation)冒泡
我们的页面可以理解为一棵DOM树,当我们在叶子结点上做什么事情的时候(如click一个a元素),如果我们不人为的设置stopPropagation(Moder Browser), cancelBubble(IE),那么它的所有父元素,祖宗元素都会受之影响,它们上面绑定的事件也会产生作用。看一个示例:
当我们在a 上面点击的时候,首先会触发它本身所绑定的click事件,然后会一路往上,触发它的父元素,祖先元素上所有绑定的click事件,就像下图演示的那样。
3).示例HTML
为了对下面的代码进行演示,添加一些HTML代码:
<ul id="members" data-role="listview" data-filter="true">
<!-- ... more list items ... -->
<li>
<a href="detail.html?id=10">
<h3>John Resig(jQuery的作者)</h3>
<p><strong>jQuery Core Lead</strong></p>
<p>Boston, United States</p>
</a>
</li>
<!-- ... more list items ... -->
</ul>
2.bind()
.bind()是最直接的绑定方法 ,会绑定事件类型和处理函数到DOM element上, 这个方法是存在最久的,而且也很好的解决了浏览器在事件处理中的兼容问题。但是这个方法有一些performance方面的问题,看下面的代码:
/* The .bind() method attaches the event handler directly to the DOM
element in question ( "#members li a" ). The .click() method is
just a shorthand way to write the .bind() method. */ $( "#members li a" ).bind( "click", function( e ) {} );
$( "#members li a" ).click( function( e ) {} );
上面的两行代码所完成的任务都是一致的,就是把event handler加到全部的匹配的<a>元素上。这里存在着一些效率方面的问题,一方面,我们隐式地把click handler加到所有的a标签上,这个过程是昂贵的;另一方面在执行的时候也是一种浪费,因为它们都是做了同一件事却被执行了一次又一次(比如我们可以把它hook到它们的父元素上,通过冒泡可以对它们中的每一个进行区分,然后再执行这个event handler)。
优点:
·这个方法提供了一种在各种浏览器之间对事件处理的兼容性解决方案;
·非常方便简单的绑定事件到元素上;
·.click(), .hover()...这些非常方便的事件绑定,都是bind的一种简化处理方式;
·对于利用ID选出来的元素是非常好的,不仅仅是很快的可以hook上去(因为一个页面只有一个id),而且当事件发生时,handler可以立即被执行(相对于后面的live, delegate)实现方式;
缺点:
·它会绑定事件到所有的选出来的元素上;
·它不会绑定到在它执行完后动态添加的那些元素上;
·当元素很多时,会出现效率问题;
·当页面加载完的时候,你才可以进行bind(),所以可能产生效率问题;
3.live()
.live()方法用到了事件委托的概念来处理事件的绑定。它和用.bind()来绑定事件是一样的。.live()方法会绑定相应的事件到你所选择的元素的根元素上,即是document元素上。那么所有通过冒泡上来的事件都可以用这个相同的handler来处理了。它的处理机制是这样的,一旦事件冒泡到document上,jQuery将会查找selector/event metadata,然后决定那个handler应该被调用。jquery 1.8.2的源码:
if (delegateCount && !(event.button && event.type === "click")) { for (cur = event.target; cur != this; cur = cur.parentNode || this) { // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
if (cur.disabled !== true || event.type !== "click") {
selMatch = {};
matches = [];
for (i = 0; i < delegateCount; i++) {
handleObj = handlers[i];
sel = handleObj.selector; if (selMatch[sel] === undefined) {
selMatch[sel] = handleObj.needsContext ?
jQuery(sel, this).index(cur) >= 0 :
jQuery.find(sel, this, null, [cur]).length;
}
if (selMatch[sel]) {
matches.push(handleObj);
}
}
if (matches.length) {
handlerQueue.push({ elem: cur, matches: matches });
}
}
}
}
当handler在执行的时候,因为有冒泡的参与,确实会有一些延迟,但是绑定的时候是特别的快。
/* The .live() method attaches the event handler to the root level
document along with the associated selector and event information
( "#members li a" & "click" ) */ $( "#members li a" ).live( "click", function( e ) {} );
上面的code在和.bind()相比的时候有一个好处就是我们不需要在每个元素上再去绑定事件,而只在document上绑定一次就可以了。尽管这个不是最快的方式,但是确实是最少浪费的。
优点:
·这里仅有一次的事件绑定,绑定到document上而不像.bind()那样给所有的元素挨个绑定;
·那些动态添加的elemtns依然可以触发那些早先绑定的事件,因为事件真正的绑定是在document上;
·你可以在document ready之前就可以绑定那些需要的事件;
缺点:
·从1.7开始已经不被推荐了,所以你也要开始逐步淘汰它了;
·Chaining没有被正确的支持;
·当使用event.stopPropagation()是没用的,因为都要到达document;
·因为所有的selector/event都被绑定到document, 所以当我们使用matchSelector方法来选出那个事件被调用时,会非常慢;
·当发生事件的元素在你的DOM树中很深的时候,会有performance问题;
4.delegate()
.delegate()有点像.live(),不同于.live()的地方在于,它不会把所有的event全部绑定到document,而是由你决定把它放在哪儿。而和.live()相同的地方在于都是用event delegation.
/* The .delegate() method behaves in a similar fashion to the .live()
method, but instead of attaching the event handler to the document,
you can choose where it is anchored ( "#members" ). The selector
and event information ( "li a" & "click" ) will be attached to the
"#members" element. */ $( "#members" ).delegate( "li a", "click", function( e ) {} );
优点:
·你可以选择你把这个事件放到那个元素上了;
·chaining被正确的支持了;
·jQuery仍然需要迭代查找所有的selector/event data来决定那个子元素来匹配,但是因为你可以决定放在那个根元素上,所以可以有效的减小你所要查找的元素;
·可以用在动态添加的元素上;
缺点:
·需要查找那个那个元素上发生了那个事件了,尽管比document少很多了,不过,你还是得浪费时间来查找;
5.on()
其实.bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的,这是1.8.2的源码:
bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
unbind: function( types, fn ) {
return this.off( types, null, fn );
}, live: function( types, data, fn ) {
jQuery( this.context ).on( types, this.selector, data, fn );
return this;
},
die: function( types, fn ) {
jQuery( this.context ).off( types, this.selector || "**", fn );
return this;
}, 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 );
},
看一下,我们用如何用.on()来改写前面通过 .bind(), .live(), .delegate()所注册的事件:
/* The jQuery .bind(), .live(), and .delegate() methods are just one
line pass throughs to the new jQuery 1.8.2 .on() method */ // Bind
$( "#members li a" ).on( "click", function( e ) {} );
$( "#members li a" ).bind( "click", function( e ) {} ); // Live
$( document ).on( "click", "#members li a", function( e ) {} );
$( "#members li a" ).live( "click", function( e ) {} ); // Delegate
$( "#members" ).on( "click", "li a", function( e ) {} );
$( "#members" ).delegate( "li a", "click", function( e ) {} );
优点:
·提供了一种统一绑定事件的方法;
·仍然提供了.delegate()的优点,当然如果需要你也可以直接用.bind();
缺点:
·也许会对你产生一些困扰,因为它隐藏了一前面我们所介绍的三种方法的细节;
6.结论
·用.bind()的代价是非常大的,它会把相同的一个事件处理程序hook到所有匹配的DOM元素上;
·不要再用.live()了,它已经不再被推荐了,而且还有许多问题;
·.delegate()会提供很好的方法来提高效率,同时我们可以添加一事件处理方法到动态添加的元素上;
·我们可以用.on()来代替上述的3种方法;
参考资料
[1].http://www.elijahmanor.com/2012/02/differences-between-jquery-bind-vs-live.html
[2].http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/
jQuery事件绑定方法bind、 live、delegate和on的区别的更多相关文章
-
jQuery事件委托方法 bind live delegate on
1.bind jquery 1.3之前 定义和用法:主要用于给选择到的元素上绑定特定事件类型的监听函数 语法: bind(type,[data],function(e)); 特点: a.适合页 ...
-
jQuery三种事件绑定方式.bind(),.live(),.delegate()
.bind(), .live(), 和 .delegate()之间的区别并不明显.但是理解它们的不同之处有助于写出更简洁的代码,并防止我们的交互程序中出现没有预料到的bug. 基础 DOM树 首先,图 ...
-
完美的jquery事件绑定方法on()
在讲on()方法之前,我们先讲讲在on()方法出现前的那些事件绑定方法: .live() jQuery 1.3新增的live()方法,使用方法例如以下: $("#info_table td& ...
-
JQuery事件绑定,bind与on区别
jquery事件绑定bind:向匹配元素添加一个或多个事件处理器 $(selector).bind("click",data,function); live:向当前或未来的匹配元素 ...
-
jquery 事件委托三种事件绑定方式.bind(),.live(),.delegate()
http://www.ituring.com.cn/article/467# http://www.cnblogs.com/lvdabao/archive/2013/08/30/3290603.htm ...
-
jQuery事件:bind、delegate、on的区别
最近在AngularJS的开发中,遇到一个神奇的事情:我们用到livebox来预览评论列表中的图片, 然而评论列表是由Angular Resource动态载入的.不可思议的是,点击这些动态载入的图片仍 ...
-
原生JS事件绑定方法以及jQuery绑定事件方法bind、live、on、delegate的区别
一.原生JS事件绑定方法: 1.通过HTML属性进行事件处理函数的绑定如: <a href="#" onclick="f()"> 2.通过JavaS ...
-
jQuery事件绑定—on()、bind()与delegate()
啃了一段日子的js相关了,学的过程中发现在jQuery中绑定事件时,有人用bind(),有人用on(),有人用delegate(),还有人用live(),看代码的时候觉得都实现功能了也就掀过去了,只是 ...
-
jQuery中的事件绑定方法
在jQuery中,事件绑定方法大致有四种:bind(),live(), delegate(),和on(). 那么在工作中应该如何选择呢?首先要了解四种方法的区别和各自的特点. 在了解这些之前,首先要知 ...
随机推荐
-
SQL经典面试题及答案
1.一道SQL语句面试题,关于group by表内容:2005-05-09 胜2005-05-09 胜2005-05-09 负2005-05-09 负2005-05-10 胜2005-05-10 负2 ...
-
Android性能优化方法(九)
通常我们写程序,都是在项目计划的压力下完成的,此时完成的代码可以完成具体业务逻辑,但是性能不一定是最优化的.一般来说,优秀的程序员在写完代码之后都会不断的对代码进行重构.重构的好处有很多,其中一点,就 ...
-
BZOJ-1207 打鼹鼠 DP(LIS)
1207: [HNOI2004]打鼹鼠 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2276 Solved: 1116 [Submit][Statu ...
-
Date and Time in PeopleCode
Setting a Date to Null in PeopleCode To set a date to null in PeopleCode either use the SetDefault() ...
-
delphi各种错
1. 保存文件form_spml时出上面的错,点yes后还是会出错. 解决:有时间要关闭delphi2006软件才会跳出“remove/redirect the links to another mo ...
-
Python基础__Python序列基本类型及其操作(1)
本节考虑的Python的一个中要的内置对象序列, 所谓的序列即一个有序对象的集合.这里的对象可以是数字.字符串等.根据功能的不同将序列分为字符串.列表.元组,本文将以下这几种对象做一些介绍. 一. 字 ...
-
codevs 1766 装果子
提交地址:http://codevs.cn/problem/1766/ 1766 装果子 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 De ...
-
flask微服务框架的初步接触
测试2个关联的系统接口时,经常会遇到被测试系统或被测app的处理内部处理流程会依赖另一个系统的接口返回结果,这时,常用的做法就是写一个模拟测试桩,用作返回请求时的结果.java可以用servicele ...
-
Visible Lattice Points SPOJ - VLATTICE 三维+莫比乌斯反演
#include<bits/stdc++.h> #define ll long long using namespace std; ; int vis[maxn]; int mu[maxn ...
-
nginx配置基于域名、端口、IP的虚拟主机
1.基于域名的虚拟主机: 绝大多数企业对外提供服务的网站使用的都是基于域名的主机,通过不同的域名区分不同的虚拟主机. 首先我们进入安装nginxd的目录下:/application/nginx-1.6 ...