jQuery的事件委托机制和事件绑定的区别

首先看一下DOM树:


当我们点击一个事件的时候,其触发了连接元素的单击事件,该事件则引发任何我们已经绑定到该元素的单击事件上的函数的执行。

例如:

     $('a').bind('click',function(){

alert("hello world");

})

click事件接着会向树的根方向传播最终会传播到window对象,

在操纵DOM的语境中,document是根节点。

1:.bind()事件

 如上例所示,jQuery扫描文件找出所用的$('a')元素,并把alert函数绑定到每个元素的click事件上。

2:.live()事件

 如:$('a').live('click',function(){

     alert('hello world');

})

JQuery把alert函数绑定到$(document)元素上,并使用’click’和’a’作为参数。任何时候只要有事件冒泡到document节点上,它就查看该事件是否是一个click事件,以及该事件的目标元素与’a’这一CSS选择器是否匹配,如果都是的话,则执行函数。
  live方法还可以被绑定到具体的元素(或“context”)而不是document上,像这样:

[javascript]  view plain  copy
  1. $('a', $('#container')[0]).live(...);   
3:delegate事件

[javascript]  view plain  copy
  1. $('#container').delegate('a''click'function() { alert("That tickles!") });   
  JQuery扫描文档查找$(‘#container’),并使用click事件和’a’这一CSS选择器作为参数把alert函数绑定到$(‘#container’)上。任何时候只要有事件冒泡到$(‘#container’)上,它就查看该事件是否是click事件,以及该事件的目标元素是否与CCS选择器相匹配。如果两种检查的结果都为真的话,它就执行函数。
  可以注意到,这一过程与.live()类似,但是其把处理程序绑定到具体的元素而非document这一根上。精明的JS’er们可能会做出这样的结论,即$('a').live() == $(document).delegate('a'),是这样吗?嗯,不,不完全是。

现在用的比较多的就是on了

 通过查看jQuery的源代码(我查看的版本是1.12.4),可以发现无论bind()还是delegate()都是通过on()方法实现的,只是参数不同,如下图: 
这里写图片描述


直接绑定和事件委托

1:直接绑定:大多数浏览器的事件冒泡,都是从文档的最深、最内层发生事件的元素(也称为event target——事件目标),一路向上到达body或document元素上。在IE8和之前的版本上,少数事件例如change、submit不支持原生的事件冒泡,但jQuery模拟并创建了一致的、跨浏览器的事件冒泡行为。

如果on()方法的selector 参数为空,事件处理程序就被称为直接绑定。每当在被绑定元素上(如下例中被绑定的document元素,译者注)发生事件时,无论这个事件发生在这个元素上还是从内层元素经冒泡而来,该处理程序都会被调用。

      并且,如果on()方法的selector 参数为空,它与bind()方法相同——只能绑定页面已有元素的事件。

下面我们用代码说明什么是直接绑定

<body>
<div>
        这是一个div
        <button>点击</button>
</div>
<script type="text/javascript">
        $(function(){
            //将click事件绑定在document对象上,
            //页面上任何元素发生的click事件都冒泡到document对象上得到处理
            //从而调用事件处理程序
            //本例为了简单绑定到了document,实际上绑定到那个元素上都有类似效果
            $(document).on("click",function(e){
               console.log(e.target.tagName + " is clicked")
            })  
        })
    </script>
</body>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

      页面执行效果如下图: 
这里写图片描述

      如果on()方法的selector 参数不为空,事件处理程序就被称为委托。当事件直接发生在被绑定的元素上(如下例中绑定到document上,译者注)时,该程序不会被调用,而只有当事件发生在与选择器匹配的内部元素上(如下例中click事件发生在button上,译者注)时,才会调用该程序。

      

jQuery的事件委托是将事件从事件的发生者(即event target,译者注)一直向上冒泡到绑定了事件处理程序的元素上(例如从最内层元素向上冒泡到最外层元素),并为冒泡“沿路”过程中匹配的所有选择器执行事件处理程序。

      下面我们用代码说明什么是委托

<body>
    <div>
        这是一个div
        <button>点击</button>
    </div>
    <script type="text/javascript">
        $(function(){
            //将click事件绑定在document对象上,
            //并传入第二个可选参数:selector
            //当事件冒泡到document对象时,检测事件的target,
            //如果与传入的选择符(这里是button)匹配,就调用事件处理程序即触发事件,否则不触发。
            $(document).on("click","button",function(e){
                console.log(e.target.tagName + " is clicked")
            })
        })
    </script>
    </body>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

      面执行效果如下图: 
这里写图片描述

事件处理程序只会被绑定到当前已被选定的元素上(如上例中的document元素上,译者注),这些元素在调用on()方法时必须已经存在——同bind()。

为了确保这些元素已经存在并能被选中,请将代码放置到</body>标签之前或者在$(function(){ ... })内执行事件绑定。或者,使用事件委托来绑定事件处理程序。

      

事件委托的优点 
      1、能处理来自于内层子元素的事件,这些内层子元素是在稍后时间里被添加的文档中的。通过选择一个在绑定事件委托处理程序时肯定存在的元素,就可以使用事件委托来避免 需要频繁的添加和删除事件处理程序的操作。 
      这个元素可以是MVC模式下的一个视图容器元素或者是document元素(如果事件处理程序需要监听文档中的全部冒泡事件)。在加载任何html代码之前,document元素已经在html文档的头部存在了,所以无需等待dom ready就可以在document这个元素上绑定事件了,这是安全可靠的。

      2、除了可以处理尚未创建的内层子元素的事件,事件委托的另一个优点是:当需要监听很多元素时,事件委托的性能更好。

例如:有一个1000行数据的表格,下面的代码就是将一个事件处理程序绑定到这1000个元素上,事件绑定需要执行1000次。

$( "#dataTable tbody tr" ).on( "click", function() {
  console.log( $( this ).text() );
});
 
 
  • 1
  • 2
  • 3

      事件委托方式(如下代码)是将事件处理程序绑定到一个元素上,即tbody上,事件只需向上冒泡一级(从被点击的tr元素到tbody元素)。事件只需绑定一次,然后采用事件冒泡来触发事件。

$( "#dataTable tbody" ).on( "click", "tr", function() {
  console.log( $( this ).text() );
});
 
 
  • 1
  • 2
  • 3

以上内容翻译自:http://api.jquery.com/on/ 《Direct and delegated events》一节

总结

1.选择器匹配到的元素比较多时,不要用bind()迭代绑定 
2.用id选择器时,可以用bind() 
3.需要给动态添加的元素绑定时,用delegate()或者on() 
4.用delegate()和on()方法,dom树不要太深 
5.尽量使用on()来代替delegate()和bind() 
6.在需要为较多的元素绑定事件的时候,优先考虑事件委托,可以带来性能上的好处 
7.bind()和delegate()都是通过on()方法实现的,只是参数不同——当on()的selector参数为空时,其效果完全等同于bind();当selector参数不为空时,其效果完全等同于delegate(); 
8.使用.on()方法时,事件只会绑定到$()函数的选择符表达式匹配的元素上(上面例子中,为了简单绑定到了document),因此可以精确地定位到页面中的一部分,从而减少事件冒泡的开销。

停止传播

  最后一个我想做的提醒与事件传播有关。通常情况下,我们可以通过使用这样的事件方法来终止处理函数的执行:
[javascript]  view plain  copy
  1. $('a').bind('click'function(e) {    
  2. e.preventDefault();    
  3. // 或者    
  4. e.stopPropagation();    
  5. });    
  不过,当我们使用live或是delegate方法的时候,处理函数实际上并没有在运行,需要等到事件冒泡到处理程序实际绑定的元素上时函数才会运行。而到此时为止,我们的其他的来自.bind()的处理函数早已运行了。

原文出处: 点击打开链接


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值