事件委托技术原理和使用(js,jquery)

原创 2016年03月10日 11:18:56
  • 标签:
  • 技术 /
  • jquery /
  • javascript
  • 2555

一:事件委托技术原理 摘自http://www.webhek.com/event-delegate/

事件委托(event delegation),使用时间委托技术能让你避免对特定的每个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上。事件监听器会分析从子元素冒泡上来的事件,找到哪个是子元素的事件。

首先,我们设定一个列表

<ul id="parent-list"><li id="post-1">Item 1</li><li id="post-2">Item 2</li><li id="post-3">Item 3</li><li id="post-4">Item 4</li><li id="post-5">Item 5</li><li id="post-6">Item 6</li>
</ul>

我们假设要给每个li添加不同的事件,你可以给每个独立的li元素添加事件监听器,但有时这些li元素可能会被删除,可能会有新增,监听它们的新增或删除事件将会是一场噩梦,尤其是当你的监听事件的代码放在应用的另一个地方时。但是,如果你将监听器安放到它们的父元素上呢?你如何能知道是那个子元素被点击了?

简单:当子元素的事件冒泡到父ul元素时,你可以检查事件对象的target属性,捕获真正被点击的节点元素的引用。下面是一段很简单的JavaScript代码,演示了事件委托的过程:

[html] view plain copy
  1. //找到父元素,添加监听器。。。
  2. document.getElementById('parent-list').addEventListener('click', function (e) {
  3. //e.target是被点击的元素
  4. //如果被点击的是li元素
  5. if(e.target && e.target.nodeName == 'Li') {
  6. //执行操作,,,
  7. console.log('List item', e.target.id.replace('post-'), "was clicked")
  8. }
  9. })

第一步是给父元素添加事件监听器。当有事件触发监听器时,检查事件的来源,排除非li子元素事件。如果是一个li元素,我们就找到了目标!如果不是一个li元素,事件将被忽略。这个例子非常简单,ULli是标准的父子搭配。让我们试验一些差异比较大的元素搭配。假设我们有一个父元素div,里面有很多子元素,但我们关心的是里面的一个带有”classA” CSS类的A标记:

[javascript] view plain copy
  1. //获取父元素DIV,添加监听器
  2. document.getElementById('myDiv').addEventListener('click', function (e) {
  3. //e.target是被点击的节点
  4. if (e.target && e.target.nodeName == 'A') {
  5. //获取css类名
  6. var classes = e.target.className.split(' ');
  7. if (classes) {
  8. for (var x = 0; x< class.length; x++) {
  9. if (class[x] == 'classA') {
  10. //找到元素 可以操作了
  11. console.log('Anchor element clicked');
  12. }
  13. }
  14. }
  15. }
  16. })

上面这个例子中不仅比较了标签名,而且比较了CSS类名。虽然稍微复杂了一点,但还是很具代表性的。比如,如果某个A标记里有一个span标记,则这个span将会成为target元素。这个时候,我们需要上溯DOM树结构,找到里面是否有一个 A.classA 的元素。

二:jquery中事件委托优化http://www.jb51.net/article/28770.htm

jQuery为绑定和委托事件提供了.bind()、.live()和.delegate()方法。本文在讨论这几个方法内部实现的基础上,展示它们的优劣势及适用场合。

事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)。

.bind

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

bind()只能给调用它的时候已经存在的元素绑定事件,不能给未来新增的元素绑定事件(类似于新来的员工收不到快递)

.live

$("#info_table td").live("click",function(){/*显示更多信息*/}); 解决了.bind的问题,将事件绑定到document对象,能够处理后续添加元素的单击事件

缺点:

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

解决方法:

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

[html] view plain copy
  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()方法时配合使用一个上下文参数:

$("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中尚不存在的元素绑定事件;

PS:根据jQuery 1.7 Beta 1的发版说明,jQuery 1.7为了解决.bind()、.live()和.delegate()并存造成的不一致性问题,将会增加一对新的事件方法:.on()和.off():
$(elems).on(events, selector, data, fn);
$(elems).off(events, selector, fn);
如果指定selector,则为事件委托;否则,就是常规绑定。新旧API对应如下: 

事件委托技术原理和使用(js,jquery)相关推荐

  1. js事件委托及其原理

    什么是事件委托:通俗的讲,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事 ...

  2. “约见”面试官系列之常见面试题之第六十六篇之事件委托的原理和实现(建议收藏)

    事件委托(事件代理)原理:简单的说就是将事件交由别人来执行,就是将子元素的事件通过冒泡的形式交由父元素来执行. 为什么要用时间委托? 在JavaScript中,添加到页面上的事件处理程序数量将直接关系 ...

  3. 什么是事件委托?事件委托的原理以及优缺点

    事件委托又称事件代理, 下面将要将要简要叙述一下这种方法的原理及优点 一什么是事件委托? 我们看下面的例子: 假使我们需要对 3 个 li 元素添加点击事件: 传统的方法是分别给每个 li 元素绑定 ...

  4. JavaScript之事件委托(附原生js和jQuery代码)

    事件委托的原理依赖于事件冒泡,可以通过给父元素的事件委托来确定是哪个子元素触发了事件从而做一系列操作. 使用事件委托的优点 1.操作子元素时不用一一遍历,可以根据事件触发的对象而进行相应操作 dom结 ...

  5. js原生事件委托写法,jquery事件委托写法

    什么是事件委托: 事件委托--给父元素绑定事件,用来监听子元素的冒泡事件,并找到是哪个子元素的事件.(不理解冒泡的可以去百度下) 定义: 利用事件冒泡处理动态元素事件绑定的方法,专业术语叫事件委托. ...

  6. 原生JS及jQuery中事件委托的写法

    在绑定节点事件处理程序时遇到的问题: 每个 函数都是对象,都会占用内存:内存中的对象越多,性能就越差. 其次,必须事先指定所有事件处理程 序而导致的 DOM访问次数,会延迟整个页面的交互就绪时间. 采 ...

  7. JS事件委托(什么情况下使用事件委托)

    1. 什么是事件委托 事件委托:把事情委托给别人,代为处理. 事件委托也称为事件代理,在 jQuery 里面称为事件委派. 理解:说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的 ...

  8. js中的事件委托或是事件代理详解(转载)

    起因: 1.这是前端面试的经典题型,要去找工作的小伙伴看看还是有帮助的: 2.其实我一直都没弄明白,写这个一是为了备忘,二是给其他的知其然不知其所以然的小伙伴们以参考: 概述: 那什么叫事件委托呢?它 ...

  9. js 事件委托深入浅出

    JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件.那这是什么意思呢?事件委托到底是一个什么原理: 有三个同事预计会在同一天收到快递. ...

最新文章

  1. Android.mk 用法介绍
  2. 学习LOWORD、 HIWORD、LOBYTE、HIBYTE
  3. 机器学习导论(张志华):基本概念
  4. VB讲课笔记06:窗体与常用控件
  5. 5G版iPhone更多细节曝光:骁龙X55基带+A14处理器
  6. 产品规格说明书怎么写_产品说明都不会写?亚马逊旺季请靠边站!
  7. 解决Spring Boot集成Shiro,配置类使用Autowired无法注入Bean问题
  8. 2 万字长文盘点五种负载均衡策略
  9. 差速齿轮原理_减速箱差速器行星轮圆柱销失效分析
  10. wamp怎么安装mysql服务器_使用WAMPServer套件可安装Apache服务器和MySQL服务器
  11. js中鼠标事件mouseover、mouseenter和mouseleave、mouseout的区别
  12. 【AI创新者】图森未来CTO侯晓迪:定义问题比解决问题更重要
  13. php做网站需要的技术,建网站需要什么技术
  14. 用故障恢复控制台恢复注册表
  15. 买个云服务器搭建自己的ngrok做微信公众号开发
  16. 51单片机控制TB6600驱动器驱动42步进电机
  17. 112123---123456
  18. 计算机视觉相关词汇翻译
  19. 远程桌面端口不是3389,怎么连接
  20. Java的方式生成条形码

热门文章

  1. java自定义监听器例子_Spring 实现自定义监听器案例
  2. Zabbix使用JMX监控tomcat
  3. 命令行参数tail c语言,osg学习笔记2, 命令行参数解析器ArgumentParser
  4. 伤感网络验证系统_可验证云数据库架构与设计
  5. 语言输出奇树有多少总方法_如何学习一门编程语言?这些方法告诉你,不要再说你不会学习...
  6. vue如何sleep_Java常见面试题 非常实用【个人经验】
  7. java socket编程 select_windows socket编程select模型使用
  8. python字典作业_python第一天作业:字典
  9. i是j的倍数c语言编程,【图片】【编程!】记录我C语言的一步步【极度恐慌漫画吧】_百度贴吧...
  10. Linux系统设置全局的默认网络代理