jQuery绑定方法的区别 - .bind() / .live() / .delegate() / .on()

介绍

本文只对原文重点内容做出翻译,几乎涵盖所有原文内容,如仍有疑惑请参考原文,地址在文章最下方给出。

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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</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>  

bind方法

bind方法直接把事件类型与事件句柄注册到所有满足选择器条件的DOM元素中。该方法经过长期的考验,直接可靠,只是会有些性能问题。如下

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 ) {} );   

上面两种方式的效果一摸一样,所有的链接都会独立绑定到同一个事件控制句柄,比较浪费资源。

优势 - 跨浏览器、方便快捷、支持快捷方法(.click()、.hover()等)、事件触发时响应速度快。

劣势 - 每个元素绑定同一个句柄副本(正确做法是绑定同一个句柄的引用)、无法应对动态加入的元素、元素多的时候会有性能问题、影响页面加载速度。

live方法

live采用事件委托的概念,其调用方式与bind类似。它将事件句柄连同选择器和事件信息一起绑定到document,这样就可以让事件句柄作用于所有事件。当事件冒泡至document时,jQuery则会查看选择器和事件来决定是否调用句柄。这种方式会在用户操作时多多少少有些影响性能,但初始注册时却很快。

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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 ) {} );  

上面的代码与bind比起来,只需要把事件句柄绑定到document上就可以了,无需对所有满足条件的DOM元素一一绑定。这样做不仅效率高,而且节省资源,但这并不意味着这种方案毫无瑕疵。

优势 - 与bind方式相比,只需要一个事件句柄实例;从bind升级到live改动很小,只需要替换方法名字即可;动态添加到DOM树中,并满足选择器条件的元素也能按预期设想的那样工作,因为实际绑定的时候document元素,并非真实的目标DOM元素;句柄绑定可以在document的ready事件前完成,充分利用加载时间。

劣势 - jQuery 1.7中已不推荐使用该方法;这个方法对链式操作控制的不好;选择器中选出的元素基本上算是作废了,因为事件句柄是注册到document的;event.stopPropagation()不再起作用,因为document已经全权代理所有事件;因为所有的选择器和事件信息都是绑定到document的,所以在事件发生时jQuery会使用matchesSelector从大量的信息中找出匹配项来执行对应的事件句柄;事件会一直传播到document,如何DOM层次很深的话会对性能产生影响。

delegate方法

delegate的实现思路与live类似,但并不要求必须绑定到document,开发人员可以自行决定绑定元素。

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* The .delegate() method behaves in a similar fashion to the .live()  
  2.    method, but instead of attaching the event handler to the document,  
  3.    you can choose where it is anchored ( "#members" ). The selector  
  4.    and event information ( "li a" & "click" ) will be attached to the  
  5.    "#members" element. */  
  6.    
  7. $( "#members" ).delegate( "li a""click"function( e ) {} );  

delegate的功能非常很强悍。上面的代码将事件句柄与事件信息一起注册到无序列表("#members")。这要比live总是注册到document的做法高效得多。另外delegate还解决了许多其它问题。

优势 - 目标绑定元素可指定;选择器不会预先执行,只是用来注册到根元素;支持链式操作;jQuery仍旧便利注册内容来查找匹配的选择器和事件,只是数据量相比document来说已经大大减少;适用于动态添加的元素;如果绑定对象为document,那么绑定操作可以在document的ready事件前执行。

劣势 - bind到delegate的过渡并不平滑,因为毕竟方法签名有出入;jQuery会使用matchesSelector并根据根元素中保存的选择器和事件信息来判断调用哪个句柄,其中的存储信息数量不容小视,只是与live相比还算是小的。

on方法

我们所熟知的bind、live和delegate底层都是靠jQuery 1.7中的新方法on实现的;unbind、die和undelegate则是通过off实现的。具体细节请参见下面的代码:

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // ... more code ...  
  2.    
  3. bind: function( types, data, fn ) {  
  4.     return this.on( types, null, data, fn );  
  5. },  
  6. unbind: function( types, fn ) {  
  7.     return this.off( types, null, fn );  
  8. },  
  9.    
  10. live: function( types, data, fn ) {  
  11.     jQuery( this.context ).on( types, this.selector, data, fn );  
  12.     return this;  
  13. },  
  14. die: function( types, fn ) {  
  15.     jQuery( this.context ).off( types, this.selector || "**", fn );  
  16.     return this;  
  17. },  
  18.    
  19. delegate: function( selector, types, data, fn ) {  
  20.     return this.on( types, selector, data, fn );  
  21. },  
  22. undelegate: function( selector, types, fn ) {  
  23.     return arguments.length == 1 ?   
  24.         this.off( selector, "**" ) :   
  25.         this.off( types, selector, fn );  
  26. },  
  27.    
  28. // ... more code ...  

on的使用方式如下:

[javascript]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /* The jQuery .bind(), .live(), and .delegate() methods are just one  
  2.    line pass throughs to the new jQuery 1.7 .on() method */  
  3.    
  4. // Bind  
  5. $( "#members li a" ).on( "click"function( e ) {} );   
  6. $( "#members li a" ).bind( "click"function( e ) {} );   
  7.    
  8. // Live  
  9. $( document ).on( "click""#members li a"function( e ) {} );   
  10. $( "#members li a" ).live( "click"function( e ) {} );  
  11.    
  12. // Delegate  
  13. $( "#members" ).on( "click""li a"function( e ) {} );   
  14. $( "#members" ).delegate( "li a""click"function( e ) {} );  

on看起来像是一个拥有不同签名、经过重载的方法。

优势 - 为各种事件绑定方法提供了一致的解决方案;简化jQuery代码,无需通过bind、live和delegate进行二次调用;在能够保证拥有delegate方法所有优点的前提下,同时拥有bind方法所提供的好处。

劣势 - 稍微有点混乱,其行为取决于被调用的方式。

总结

如何在合适的场景使用合适的方法:

使用bind方法开销比较大,因为它会把同一个事件句柄附加到选择器筛选出来的每一个元素。
不要使用live方法因为官方已经把它定位为deprecated,而且使用时还有许多问题。
delegate物超所值,既能满足性能上的需求,又能自如应对动态添加的元素。
新的on方法算得上是一种语法糖,替代bind、live和delegate。
新方向是使用on方法。熟悉它的语法并开始尝试在jQuery 1.7+项目中使用。

参考文档:
http://www.elijahmanor.com/differences-between-jquery-bind-vs-live-vs-delegate-vs-on/
https://gist.github.com/elijahmanor/1749717

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值