jQuery事件绑定方法bind、 live、delegate和on的区别

我们试图绑定一些事件到DOM元素上的时候,我相信上面这4个方法是最常用的。而它们之间到底有什么不同呢?在什么场合下用什么方法是最有效的呢?

1.准备知识

当我们在开始的时候,有些知识是必须具备的:

1).DOM树

下图仅仅是一个示例,这是一个在browser环境下的一棵模拟DOM树,在下面的代码中仅起到演示的作用:

2).Event bubbling (aka event propagation)冒泡

我们的页面可以理解为一棵DOM树,当我们在叶子结点上做什么事情的时候(如click一个a元素),如果我们不人为的设置stopPropagation(Moder Browser), cancelBubble(IE),那么它的所有父元素,祖宗元素都会受之影响,它们上面绑定的事件也会产生作用。看一个示例:

复制内容到剪贴板程序代码

$(‘a‘).bind(‘click‘, function() { alert("That tickles!") });

当我们在a 上面点击的时候,首先会触发它本身所绑定的click事件,然后会一路往上,触发它的父元素,祖先元素上所有绑定的click事件,就像下图演示的那样。

3).示例HTML

为了对下面的代码进行演示,添加一些HTML代码:

复制内容到剪贴板程序代码

 1 <ul id="members" data-role="listview" data-filter="true">
 2     <!-- ... more list items ... -->
 3     <li>
 4         <a href="detail.html?id=10">
 5             <h3>John Resig(jQuery的作者)</h3>
 6             <p><strong>jQuery Core Lead</strong></p>
 7             <p>Boston, United States</p>
 8         </a>
 9     </li>
10     <!-- ... more list items ... -->
11 </ul>

2.bind()

.bind()是最直接的绑定方法 ,会绑定事件类型和处理函数到DOM element上, 这个方法是存在最久的,而且也很好的解决了浏览器在事件处理中的兼容问题。但是这个方法有一些performance方面的问题,看下面的代码:

复制内容到剪贴板程序代码

1 /* The .bind() method attaches the event handler directly to the DOM
2    element in question ( "#members li a" ). The .click() method is
3    just a shorthand way to write the .bind() method. */
4
5 $( "#members li a" ).bind( "click", function( e ) {} );
6 $( "#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的源码:

复制内容到剪贴板程序代码

 1 if (delegateCount && !(event.button && event.type === "click")) {
 2
 3     for (cur = event.target; cur != this; cur = cur.parentNode || this) {
 4
 5         // Don‘t process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764)
 6         if (cur.disabled !== true || event.type !== "click") {
 7             selMatch = {};
 8             matches = [];
 9             for (i = 0; i < delegateCount; i++) {
10                 handleObj = handlers[i];
11                 sel = handleObj.selector;
12
13                 if (selMatch[sel] === undefined) {
14                     selMatch[sel] = handleObj.needsContext ?
15                         jQuery(sel, this).index(cur) >= 0 :
16                         jQuery.find(sel, this, null, [cur]).length;
17                 }
18                 if (selMatch[sel]) {
19                     matches.push(handleObj);
20                 }
21             }
22             if (matches.length) {
23                 handlerQueue.push({ elem: cur, matches: matches });
24             }
25         }
26     }
27 }

当handler在执行的时候,因为有冒泡的参与,确实会有一些延迟,但是绑定的时候是特别的快。

复制内容到剪贴板程序代码

1 /* The .live() method attaches the event handler to the root level
2    document along with the associated selector and event information
3    ( "#members li a" & "click" ) */
4
5 $( "#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的源码:

复制内容到剪贴板程序代码

 1 bind: function( types, data, fn ) {
 2     return this.on( types, null, data, fn );
 3 },
 4 unbind: function( types, fn ) {
 5     return this.off( types, null, fn );
 6 },
 7
 8 live: function( types, data, fn ) {
 9     jQuery( this.context ).on( types, this.selector, data, fn );
10     return this;
11 },
12 die: function( types, fn ) {
13     jQuery( this.context ).off( types, this.selector || "**", fn );
14     return this;
15 },
16
17 delegate: function( selector, types, data, fn ) {
18     return this.on( types, selector, data, fn );
19 },
20 undelegate: function( selector, types, fn ) {
21     // ( namespace ) or ( selector, types [, fn] )
22     return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
23 },

看一下,我们用如何用.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的区别

时间: 2024-08-26 02:51:30

jQuery事件绑定方法bind、 live、delegate和on的区别的相关文章

jQuery三种事件绑定方式.bind(),.live(),.delegate()

.bind(), .live(), 和 .delegate()之间的区别并不明显.但是理解它们的不同之处有助于写出更简洁的代码,并防止我们的交互程序中出现没有预料到的bug. 基础 DOM树 首先,图形化的HTML文档能帮助我们更好的理解.一个简单的HTML页面看起来应该像这样 事件冒泡(也称作事件传递)(Event bubbling aka event propagation) 点击一个链接,触发绑定在链接元素上的 click 事件,进而触发绑定到这个元素的click事件的函数. 1 $('a

完美的jquery事件绑定方法on()

在讲on()方法之前,我们先讲讲在on()方法出现前的那些事件绑定方法: .live() jQuery 1.3新增的live()方法,用法如下: $("#info_table td").live("click",function(){/*显示更多信息*/}); 这里的.live()方法会把click事件绑定到$(document)对象,而且只需要给$(document)绑定一次,然后就能够处理后续动态加载的单元格的单击事件.在接收到任何事件时,$(document)

JQUERY事件绑定方法研究

阅读前,我认为你需要先知道以下几点基础知识: dom对象是树形结构的 dom中的事件会从触发事件的目标节点开始逐级向上冒泡 每当我们想给某个元素绑定事件的时候,第一个想到的方法是bind,我们就先来说说bind. bind的作用是给具体的某个元素绑定事件,比如 1 $('button').bind('click',function(){}); 给所有的button元素添加了点击事件处理方法.这似乎已经可以完成大部分的事件绑定任务了,然而有一个问题它无法解决–如果某一元素是新添加的怎么办?bind

jQuery事件:bind、delegate、on的区别

最近在AngularJS的开发中,遇到一个神奇的事情:我们用到livebox来预览评论列表中的图片, 然而评论列表是由Angular Resource动态载入的.不可思议的是,点击这些动态载入的图片仍然会触发lightbox的图片预览. 难道lightbox使用先进的MutationObserver技术监听了DOM的变化?观察lightbox源码才发现,原来只是jQuery的.on()方法: $('body').on('click', 'a[rel^=lightbox], ...', funct

jQuery事件绑定on()、bind()、live()与delegate() 方法详解

jQuery事件绑定有四个方法,对应为on,off,bind,unbind,delegate,undelegate,live,die 比较和联系: 1.bind()函数只能针对已经存在的元素进行事件的设置:但是live(),on(),delegate()均支持未来新添加元素的事件设置: 2.bind()函数在jquery1.7版本以前比较受推崇,1.7版本出来之后,官方已经不推荐用bind(),替代函数为on(),这也是1.7版本新添加的函数,同样,可以 用来代替live()函数,live()函

jQuery事件绑定on()、bind()与delegate() 方法详解

本文转载:啃了一段日子的js相关了,学的过程中发现在jQuery中绑定事件时,有人用bind(),有人用on(),有人用delegate(),还有人用live(),看代码的时候觉得都实现功能了也就掀过去了,只是一直没完全弄懂之间的区别,于是今天查了下资料,自己做个总结. 之所以有这么多类型的绑定方法,是因为jQuery的版本更新的原因,如on()方法就是1.7以后出现的. jQuery的事件绑定api页面上,提到live()方法已经过时,不建议使用.所以这里我们主要就看下以下三个方法:bind(

jQuery中的事件绑定方法

在jQuery中,事件绑定方法大致有四种:bind(),live(), delegate(),和on(). 那么在工作中应该如何选择呢?首先要了解四种方法的区别和各自的特点. 在了解这些之前,首先要知道,不管你用的是(live/ bind / delegate)之中那个方法,最终都是jQuery底层都是调用on方法来完成最终的事件绑定;.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的; 因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不

Jquery中的事件绑定$(&quot;#btn&quot;).bind(&quot;click&quot;,function(){ })

Jquery中的事件绑定:$("#btn").bind("click",function(){  }) 因为每次都这么调用太麻烦,所以jquery就用$("#btn").click(function(){})来进行简化 Jquery中的事件绑定$("#btn").bind("click",function(){ })

jQuery事件绑定和委托实例

本文实例讲述了jQuery事件绑定和委托.分享给大家供大家参考.具体方法如下: jQuery事件的绑定和委托可以用多种方法实现,on()  . bind()  . live()  . delegate() ,还有one(). 有时我们可能会像下面这样绑定一个事件: 复制代码代码如下: $("#div1").click(function() {      alert("点击后触发");  }); 上面的事件绑定,我们可以通过多种方式去实现: 1. on() 复制代码代