jQuery 中bind(),live(),delegate(),on() 区别

DOM树

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

HTML DOM Structure

 

Event bubbling (aka event propagation)冒泡

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

//例1
<script type="text/javascript"> $(document).ready(function(){ $("p").click(function(){ console.log("p"); }) $("div").click(function(){ console.log("div"); }) }); </script> <body> <div> <p>请点击</p> </div> </body>

当我们在p 上面点击的时候,首先会触发它本身所绑定的click事件,然后会一路往上,触发它的父元素div上所有绑定的click事件,控制台输出了  p  div

Bind():.

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

使用方式
 
  $(selector).bind(event,data,function)
 
  event:必需项;添加到元素的一个或多个事件,例如 click,dblclick等;
 
          单事件处理:例如 $(selector).bind("click",data,function);
 
          多事件处理:1.利用空格分隔多事件,例如 $(selector).bind("click dbclick mouseout",data,function);
 
                2.利用大括号灵活定义多事件,例如 $(selector).bind({event1:function, event2:function, ...}) 
 
                3.空格相隔方式:绑定较为死板,不能给事件单独绑定函数,适合处理多个事件调用同一函数情况;
 
 
  data:可选;需要传递的参数;
 
  function:必需;当绑定事件发生时,需要执行的函数;
  
23             /*********添加单个事件处理*********/
24 
25             $(".btn-test").bind("click", function () {
 
28             });
29 
30             /********添加多个事件处理********/
31 
32             //空格相隔方式
33             $(".btn-test").bind("mouseout click", function () {
34            
36             });
37 
38             //大括号替代方式
39             $(".btn-test").bind({
40                 "mouseout": function () {
41                     alert("这是mouseout事件!");
42                 },
43                 "click": function () {
44                     $(".container").slideToggle();
45                 }
46             });
47 
48             /********删除事件处理********/
49             $(".btn-test").unbind("click");
$( "#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(),所以可能产生效率问题

.live()

  live() 向当前或未来的匹配元素添加一个或多个事件处理器;
 
使用方式
 
  $(selector).live(event,data,function)
 
  event:必需项;添加到元素的一个或多个事件,例如 click,dblclick等;
 
      单事件处理:例如 $(selector).live("click",data,function);
 
      多事件处理:1.利用空格分隔多事件,例如 $(selector).live("click dbclick mouseout",data,function);
 
            2.利用大括号灵活定义多事件,例如 $(selector).live({event1:function, event2:function, ...}) 
 
            3.空格相隔方式:绑定较为死板,不能给事件单独绑定函数,适合处理多个事件调用同一函数情况;
 
  data:可选;需要传递的参数;
 
  function:必需;当绑定事件发生时,需要执行的函数;
 
举例说明
 
23             /*********添加单个事件处理*********/
24 
25             $(".btn-test").live("click", function () {
26               
28             });
29          
31             /********添加多个事件处理********/
32 
33             //空格相隔方式
34             $(".btn-test").live("mouseout click", function () {
35                
37             });
38 
39             //大括号替代方式
40             $(".btn-test").live({
41                 "mouseout": function () {
42                     alert("这是mouseout事件!");
43                 },
44                 "click": function () {
45                     $(".container").slideToggle();
46                 }
47             });
48 
49             /********删除事件处理********/
50             $(".btn-test").die("click");
51             

.live()方法用到了事件委托的概念来处理事件的绑定。它和用.bind()来绑定事件是一样的。.live()方法会绑定相应的事件到你所选择的元素的根元素上,即是document元素上。那么所有通过冒泡上来的事件都可以用这个相同的handler来处理了。它的处理机制是这样的,一旦事件冒泡到document上,jQuery将会查找selector/event metadata,然后决定那个handler应该被调用。

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

 上面的code在和.bind()相比的时候有一个好处就是我们不需要在每个元素上再去绑定事件,而只在document上绑定一次就可以了。尽管这个不是最快的方式,但是确实是最少浪费的。

优点:

  • 这里仅有一次的事件绑定,绑定到document上而不像.bind()那样给所有的元素挨个绑定
  • 那些动态添加的elemtns依然可以触发那些早先绑定的事件,因为事件真正的绑定是在document上
  • 你可以在document ready之前就可以绑定那些需要的事件

缺点:

  • 从1.7开始已经不被推荐了,所以你也要开始逐步淘汰它了。
  • Chaining没有被正确的支持
  • 当使用event.stopPropagation()是没用的,因为都要到达document
  • 因为所有的selector/event都被绑定到document, 所以当我们使用matchSelector方法来选出那个事件被调用时,会非常慢
  • 当发生事件的元素在你的DOM树中很深的时候,会有performance问题
适用Jquery版本
 
  jquery1.9版本以下支持,jquery1.9及其以上版本删除了此方法,jquery1.9以上版本用on()方法来代替。

.Delegate()

 
  delegate() 为指定的元素(被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)。
 
使用方式 
 
  $(selector).delegate(childSelector,event,data,function)
 
  childSelector: 必需项;需要添加事件处理程序的元素,一般为selector的子元素;
 
  event:必需项;添加到元素的一个或多个事件,例如 click,dblclick等;
 
      单事件处理:例如 $(selector).delegate(childselector,"click",data,function);
 
      多事件处理:1.利用空格分隔多事件,例如 $(selector).delegate(childselector,"click dbclick mouseout",data,function);
 
            2.利用大括号灵活定义多事件,例如 $(selector).delegate(childselector,{event1:function, event2:function, ...}) 
 
            3.空格相隔方式:绑定较为死板,不能给事件单独绑定函数,适合处理多个事件调用同一函数情况;
   data:可选;需要传递的参数;
 
  function:必需;当绑定事件发生时,需要执行的函数;
 
举例说明
 
23             /***********单元素添加单事件***********/
24 
25             //按钮绑定单击事件 实现div的显示隐藏
26             $(".header").delegate("#btn-test1", "click", function () {
27             
28             });
29 
31             /***********单元素添加多事件***********/
32 
33             //空格相隔方式
34             $(".header").delegate("#btn-test1", "click mouseout", function () {
35                 $(".container").slideToggle();
36             });
37 
38             //大括号替代方式
39             $(".header").delegate("#btn-test1", {
40                 "mouseout": function () {
41                     alert("这是mouseout事件!");
42                 },
43                 "click": function () {
44                     $(".container").slideToggle();
45                 }
46             });
适用Jquery版本
 
  jquery1.4.2及其以上版本;

.delegate()有点像.live(),不同于.live()的地方在于,它不会把所有的event全部绑定到document,而是由你决定把它放在哪儿。而和.live()相同的地方在于都是用event delegation.

优点:

  • 你可以选择你把这个事件放到那个元素上了
  • chaining被正确的支持了
  • jQuery仍然需要迭代查找所有的selector/event data来决定那个子元素来匹配,但是因为你可以决定放在那个根元素上,所以可以有效的减小你所要查找的元素。
  • 可以用在动态添加的元素上

缺点:

  • 需要查找那个那个元素上发生了那个事件了,尽管比document少很多了,不过,你还是得浪费时间来查找。

.On()

 其实.bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的

看一下,我们用如何用.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()

缺点:

  • 也许会对你产生一些困扰,因为它隐藏了一前面我们所介绍的三种方法的细节。

结论:

  • 用.bind()的代价是非常大的,它会把相同的一个事件处理程序hook到所有匹配的DOM元素上
  • 不要再用.live()了,它已经不再被推荐了,而且还有许多问题
  • .delegate()会提供很好的方法来提高效率,同时我们可以添加一事件处理方法到动态添加的元素上。
  • 我们可以用.on()来代替上述的3种方法
posted @ 2015-08-28 11:11  TodayCC  阅读(77)  评论(0)    收藏  举报