jQuery事件委托

随着DOM结构的复杂化和Ajax等动态脚本技术的运用,有了较多的动态添加进来的元素,直接用JQ添加click事件会发现新添加进来的元素并不能直接选取到,在这里就需要用到事件委托方法,JQ为事件委托提供了live()、dalegate()和on()方法。

事件委托

我们知道,DOM在为页面中的每个元素分派事件时,相应的元素一般都在事件冒泡阶段处理事件。在类似 body > div > a 这样的结构中,如果单击a元素,click事件会从a一直冒泡到div和body(即document对象)。因此,发生在a上面的单击事件,div和body元素同样可以处理。而利用事件传播(这里是冒泡)这个机制,就可以实现事件委托。具体来说,事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)。

.live()

jQuery 1.3新增的live()方法,用法如下:

$("#info_table td").live("click",function(){/*显示更多信息*/});

这里的.live()方法会把click事件绑定到$(document)对象,而且只需要给$(document)绑定一次,然后就能够处理后续动态加载的单元格的单击事件。在接收到任何事件时,$(document)对象都会检查事件类型和事件目标,如果是click事件且事件目标是td,那么就执行委托给它的处理程序。

到目前为止,一切似乎很完美。可惜,事实并非如此。因为.live()方法并不完美,它有如下几个主要缺点:

  • $()函数会找到当前页面中的所有td元素并创建jQuery对象,但在确认事件目标时却不用这个td元素集合,而是使用选择符表达式与event.target或其祖先元素进行比较,因而生成这个jQuery对象会造成不必要的开销;
  • 默认把事件绑定到$(document)元素,如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失;
  • 只能放在直接选择的元素后面,不能在连缀的DOM遍历方法后面使用,即$("#infotable td").live...可以,但$("#infotable").find("td").live...不行;
  • 收集td元素并创建jQuery对象,但实际操作的却是$(document)对象,令人费解。

解决之道

为了避免生成不必要的jQuery对象,可以使用一种叫做“早委托”的hack,即在$(document).ready()方法外部调用.live():

(function($){
    $("#info_table td").live("click",function(){/*显示更多信息*/});
})(jQuery);

在此,(function($){...})(jQuery)是一个“立即执行的匿名函数”,构成了一个闭包,可以防止命名冲突。在匿名函数内部,$参数引用jQuery对象。这个匿名函数不会等到DOM就绪就会执行。注意,使用这个hack时,脚本必须是在页面的head元素中链接和(或)执行的。之所以选择这个时机,因为这时候刚好document元素可用,而整个DOM还远未生成;如果把脚本放在结束的body标签前面,就没有意义了,因为那时候DOM已经完全可用了。

为了避免事件冒泡造成的性能损失,jQuery从1.4开始支持在使用.live()方法时配合使用一个上下文参数:

$("td",$("#info_table")[0]).live("click",function(){/*显示更多信息*/});

这样,“受托方”就从默认的$(document)变成了$("#infotable")[0],节省了冒泡的旅程。不过,与.live()共同使用的上下文参数必须是一个单独的DOM元素,所以这里指定上下文对象时使用的是$("#infotable")[0],即使用数组的索引操作符来取得的一个DOM元素。

.delegate()

如前所述,为了突破单一.bind()方法的局限性,实现事件委托,jQuery 1.3引入了.live()方法。后来,为解决“事件传播链”过长的问题,jQuery 1.4又支持为.live()方法指定上下文对象。而为了解决无谓生成元素集合的问题,jQuery 1.4.2干脆直接引入了一个新方法.delegate()。

使用.delegate(),前面的例子可以这样写:

$("#info_table").delegate("td","click",function(){/*显示更多信息*/});

使用.delegate()有如下优点(或者说解决了.live()方法的如下问题):

  • 直接将目标元素选择符("td")、事件("click")及处理程序与“受拖方”$("#info_table")绑定,不额外收集元素、事件传播路径缩短、语义明确;
  • 支持在连缀的DOM遍历方法后面调用,即支持$("table").find("#info").delegate...,支持精确控制;

可见,.delegate()方法是一个相对完美的解决方案。但在DOM结构简单的情况下,也可以使用.live()。

提示:使用事件委托时,如果注册到目标元素上的其他事件处理程序使用.stopPropagation()阻止了事件传播,那么事件委托就会失效。

在下列情况下,应该使用.live()或.delegate(),而不能使用.bind():

  • 为DOM中的很多元素绑定相同事件;
  • 为DOM中尚不存在的元素绑定事件;

.on()

根据jQuery 1.7 Beta 1的发版说明,jQuery 1.7为了解决.bind()、.live()和.delegate()并存造成的不一致性问题,将会增加一对新的事件方法:.on()和.off(),以下为on()的实现方式:

.on( events [, selector ] [, data ], handler(eventObject) )

一个简单的事件绑定如 $(‘button‘).on(‘click‘,function(){}); 与bind()无二样。 在需要为较多的元素绑定事件的时候,优先考虑事件委托,可以带来性能上的好处。比如:

如上图,将click事件绑定在document对象上,页面上任何元素发生的click事件都冒泡到document对象上得到处理。

注意到.on()的描述中第二个可选参数:selector。如下图,添加了第二个参数,选择符button:

结果:

当事件冒泡到document对象时,检测事件的target,如果与传入的选择符(这里是button)匹配,就触发事件,否则不触发。

注意.on()也可以接收一个对象参数,该对象的属性是事件类型,属性值为事件处理函数。下面是官方文档的一个例子:

最后有一点,原先的live()方法,处理函数是默认绑定在document对象上不能变的,如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致较大的性能损失。而使用.on()方法,事件只会绑定到$()函数的选择符表达式匹配的元素上(上面我的例子中,为了简单绑定到了document),因此可以精确地定位到页面中的一部分,而事件冒泡的开销也可以减少。delegate()与on()同理,毕竟是用on()实现的:

.on()和.off():实现方式 $(elems).on(events, selector, data, fn);       $(elems).off(events, selector, fn); 如果指定selector,则为事件委托;否则,就是常规绑定。新旧API对应如下:

时间: 2024-08-02 15:14:55

jQuery事件委托的相关文章

jquery事件委托详解

jQuery事件委托处理流程 上一章分析jQuery.event.add的时候已经分析了事件绑定,再把绑定的部分源码抽出来 if ( !(eventHandle = elemData.handle) ) { eventHandle = elemData.handle = function( e ) { //当一个事件被调用后页面已经卸载,则放弃jQuery.event.trigger()的第二个事件, return typeof jQuery !== core_strundefined &&

jquery事件委托的原理和用途

事件委托 声明:这一篇文章只是阐述了委托事件的原理和用委托的好处还有就是在什么时候要委托合适.在这里用的是on()和off()而对于委托的其他方法(delegate().live()等)和各个方法的比较在这里并没有详细阐述,以后如果有机会在发一篇 1.什么是委托呢? a)定义:把一件事交给别人代做就叫做委托 b)问题:为什么要把事交给别人来做呢? 原因很简单:第一.自己不想做,所以交给别人 第二.自己不会做,所以交给别人来做 第三.让别人来做这一件事更有优势等等(这也是为什么要使用委托的原因)

Jquery事件委托之Safari

什么是事件委托 事件委托是Jquery中一种事件绑定的方式,不同于常见的事件绑定方式将事件绑定在目标元素上,而是将事件绑定在父级元素上通过事件冒泡来执行绑定函数. //常见的事件绑定(Jquery) $(element).click(function(){ //do something }) //事件委托(Jquery) $(parents).on("click",element,function(){ //do something }) 事件委托的原理 事件委托将事件监听绑定在目标元

JavaScript, JQuery事件委托

1.引言 现实当中,前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款.(公司也不会容忍那么多员工站在门口就为了等快递); 这种事件委托还有个好处,就是即便公司又来很多员工,前台MM照样可以签收新员工的快递,新员工即便刚来但一样拥有拿自己快件的方法: 2.概念 通俗来讲: 事件有:onclick.onmouseover.onmouseout等等:委托呢,就是让别人来做,这件事情本身是加在元素上,然而你却加载别人身上来做,完成事件: 3.原理 利用冒泡原理,将事件加在父

jquery事件委托遇到的小坑记录

<script type="text/javascript" src="../../lib/jquery-1.11.2.min.js"></script> $(document).on('click',"li", function() { //do something }); 这样的写法,在pc,安卓上都是木有问题的,但在苹果手机,平板上就没有效果, 改成: $("div#id").on('click'

【jQuery源码】事件委托

jQuery的事件绑定有几个比较优秀的特点: 1. 可以绑定不限数量的处理函数 2. 事件可以委托到祖先节点,不必一定要绑到对应的节点,这样后添加的节点也照样能被处理. 3. 链式操作 下面主要分析事件的委托设计.事件源我们成为委托节点,委托节点委托他的祖先节点替他执行事件处理,这个祖先节点被成为被委托节点. DOM的原生事件将处理绑定在相应的节点上,相应节点触发事件才能执行处理.将事件处理委托给祖先节点,这个事件处理是附加到祖先节点的.那么需要做到的是,原节点触发了事件,想要执行已经附加到祖先

深入理解-事件委托

深入理解-事件委托 2016-11-20 15:02javascript.web开发综合.性能优化JS性能优化.事件冒泡.事件委托.事件委托优化.事件委托导致性能损失 65 views 很多人是在使用事件委托的,那对于一个使用者来说,只要能正确的使用好事件委托,完成工作,就算可以了,那么你有认真的考虑过事件委托的原理,以及你的使用场景是否适合使用事件委托呢,如果需要使用事件委托,那么你是否有正确的使用呢?这里我想简单的说一下我对事件委托的理解,希望可以有机会多多交流. 概述 事件委托有哪些好处,

jQuery-1.9.1源码分析系列(十) 事件系统——事件委托

jQuery的事件绑定有几个比较优秀的特点: 1. 可以绑定不限数量的处理函数 2. 事件可以委托到祖先节点,不必一定要绑到对应的节点 3. 链式操作 下面主要分析事件的委托设计.事件源我们成为委托节点,委托节点委托他的祖先节点替他执行事件处理,这个祖先节点被成为被委托节点. DOM的原生事件将处理绑定在相应的节点上,相应节点触发事件才能执行处理.将事件处理委托给祖先节点,这个事件处理是附加到祖先节点的.那么需要做到的是,原节点触发了事件,想要执行已经附加到祖先节点的事件处理那么就需要保证祖先节

jQuery完整的事件委托(on())

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>jQuery完整的事件委托(on())</title> <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> &l