事件委托:

比喻:事件委托的事例在现实当中比比皆是。比如,有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

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

.bind()

假设有一个多行多列的表格,我们想让用户单击每个单元格都能看到与其中内容相关的更多信息(比如,通过提示条)。为此,可以为每个单元格都绑定click事件:

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

问题是,如果表格中要绑定单击事件的有10列500行,那么查找和遍历5000个单元格会导致脚本执行速度明显变慢,而保存5000个td元素和相应的事件处理程序也会占用大量内存(类似于让每个人亲自站在门口等快递)。

在前面这个例子的基础上,如果我们想实现一个简单的相册应用,每页只显示50张照片的缩略图(50个单元格),用户点击“第x页”(或“下一页”)链接可以通过Ajax从服务器动态加载另外50张照片。在这种情况下,似乎使用.bind()方法为50个单元格绑定事件又可以接受了。

事实却不然。使用.bind()方法只会给第一页中的50个单元格绑定单击事件,动态加载的后续页面中的单元格都不会有这个单击事件。换句话说,.bind()只能给调用它的时候已经存在的元素绑定事件,不能给未来新增的元素绑定事件(类似于新来的员工收不到快递)。

live()----------die()详细解说地址
事件委托可以解决上述两个问题。具体到代码上,只要用jQuery 1.3新增的.live()方法代替.bind()方法即可:

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

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

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

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

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

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

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

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

delegate()    仔细讲解链接

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

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

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

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

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

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

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

one()详细讲解地址

one() 方法为被选元素附加一个或多个事件处理程序,并规定当事件发生时运行的函数。

当使用 one() 方法时,每个元素只能运行一次事件处理器函数。

toggle()

toggle()方法用于绑定两个或多个事件处理器函数,以响应被选元素的轮流的 click 事件。

trigger()

方法触发被选元素的指定事件类型。

与 trigger() 方法相比的不同之处

  • 它不会引起事件(比如表单提交)的默认行为
  • .trigger() 会操作 jQuery 对象匹配的所有元素,而 .triggerHandler() 只影响第一个匹配元素。
  • 由 .triggerHandler() 创建的事件不会在 DOM 树中冒泡;如果目标元素不直接处理它们,则不会发生任何事情。
  • 该方法的返回的是事件处理函数的返回值,而不是具有可链性的 jQuery 对象。此外,如果没有处理程序被触发,则这个方法返回 undefined。

另:事件源

IE下 event.srcElement

FF下 event.Target

原文

另一篇链接

事件委托和JQ事件绑定总结的更多相关文章

  1. javascript事件委托和jQuery事件绑定on、off 和one

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  2. javascript 事件委托 和jQuery事件绑定on、off 和one

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  3. js事件委托和jQuery事件绑定on , off , one , bind , unbind , die

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  4. javascript事件委托和jQuery事件绑定on、off 和one以及on绑定多个事件(重要)

    一. 事件委托什么是事件委托?用现实中的理解就是:有100 个学生同时在某天中午收到快递,但这100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生.而在jQuery 中, ...

  5. javascript事件委托和jquery事件委托

    元旦过后,新年第一篇. 初衷:很多的面试都会涉及到事件委托,前前后后也看过好多博文,写的都很不错,写的各有千秋,自己思前想后,为了以后自己的查看,也同时为现在找工作的前端小伙伴提供一个看似更全方位的解 ...

  6. 整理之DOM事件阶段、冒泡与捕获、事件委托、ie事件和dom模型事件、鼠标事件

    整理之DOM事件阶段 本文主要解决的问题: 事件流 DOM事件流的三个阶段 先理解流的概念 在现今的JavaScript中随处可见.比如说React中的单向数据流,Node中的流,又或是今天本文所讲的 ...

  7. js事件捕获,事件冒泡,事件委托以及DOM事件流

    一:DOM事件流: 事件流是从页面接收事件的顺序,DOM2级事件规定事件流包括三个阶段: ①事件捕获阶段:用意在于事件达到目标之前捕获它,在事件捕获阶段事件流模型:document→html→body ...

  8. [JavaScript] JavaScript事件注册,事件委托,冒泡,捕获,事件流

    面试题 event 事件 事件委托是什么? 如何阻止事件冒泡,阻止默认事件呢? Javascript 的事件流模型都有什么? 事件绑定和普通事件有什么区别? Event 对象 Event 对象,当事件 ...

  9. 《JAVASCRIPT高级程序设计》事件委托和模拟事件

    由于事件处理程序可以为现代web应用提供交互能力,因此许多开发人员不分青红皂白向页面中添加大量的处理程序:这在某些语言中不会导致问题,但是在javascript,事件处理程序数量直接关系到页面的整体运 ...

随机推荐

  1. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版新增系统参数管理

    欲了解V3.0版本的相关内容可查看下面的链接地址. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版本发布 在V3.0版本的Web(Mvc.WebForm)与WinF ...

  2. sql rank()函数

    RANK() OVER([<partiton_by_clause>]) partition_by_clause 将from子句生成的结果集划分为应用到RANK函数的分区.  Order_b ...

  3. Configure LDAP Server(centos7 openldap)

    1.安装openldap -server: [root@dlp ~]# yum -y install openldap-servers openldap-clients [root@dlp ~]# c ...

  4. C++动态加载DLL调用方法

    一.构建DLL路径 char szTmp[_MAX_PATH]; char* szPath = getcwd(szTmp, _MAX_PATH);//获取当前工作目录  //构建dll路径  strc ...

  5. Application Engine

    Exit(1) : Terminate the AE immediately and rollback all DB changes madeexit(0) : Terminate the AE im ...

  6. c#中事物使用

    数据库事务(简称: 事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成.当事务被提交给了DBMS(数据库管理系统),则DBMS(数据库管理系统)需要确保该事务中的所有操作都 ...

  7. 在macbook上搭建ubuntu工作环境

    工作环境需要:ubuntu12.04.gcc 4.4.7.vim.source insight.git. 1. 制作启动盘 首先需要制作一个能从苹果电脑启动的ubuntu启动盘: 在苹果电脑的终端中输 ...

  8. hsql数据库使用详解(入门)及快速使用

    一.简介: hsql数据库是一款纯Java编写的免费数据库,许可是BSD-style的协议,如果你是使用Java编程的话,不凡考虑一下使用它,相对其 他数据库来说,其体积小,才563kb.仅一个hsq ...

  9. 【笔记】css hover 伪类控制其他元素

    最近在模仿一个网站的项目 当中有一个效果需要利用到hover效果因为不太想写jq脚本所以百度了一下css hover的运用发现原来hover也可以控制其他元素的变化的 但是这有一个要求 就是添加hov ...

  10. linux 下的信号量参数

    linux 下的信号量参数 转载自:http://blog.itpub.net/26110315/viewspace-718306/ 信号量是一种锁机制用于协调进程之间互斥的访问临界资源.以确保某种共 ...