首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript 事件委托 以及jQuery对事件委托的支持

JavaScript 事件委托 以及jQuery对事件委托的支持

作者头像
亦山
发布2019-05-25 09:50:37
7620
发布2019-05-25 09:50:37
举报

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1432223

      在我的另外一篇文章 解析Javascript事件冒泡机制里的最后,从冒泡机制的角度谈了一点对Javascript 事件委托的理解。现在单独把事件委托 拿出来和大家探讨一下。

什么是委托?

所谓的委托,现实意义上讲是指将自己的事务嘱托他人代为处理。比如说甲委托乙去做某些事儿,那么,甲则是委托人,乙是被委托人。真正做事情的是乙,即被委托人,而委托人甲 则是把相应的信息传递给被委托人乙,自己本该做的事情交给了乙来做,如下图这个例子:

      那么在我们javascript 里,什么是事件委托呢?

事件委托

       事件委托  允许我们不必为某些特定的节点添加事件监听器,而是将事件监听器添加到(这些节点的)某个 parent节点上。事件监听器分析冒泡事件,去找到匹配的子节点元素,然后做出相应的事件响应

     事件委托具体是怎么工作的呢? 我们从下面的简单的例子开始,给大家展示事件委托的工作原理。

先看下面一段代码:

	<div id="box1" class="box1">
		<p id="para1">Paragraph 1</p>
		<p id="para2">Paragraph 2</p>
		<p id="para3">Paragraph 3</p>
		<p id="para4">Paragraph 4</p>
		<p id="para5">Paragraph 5</p>
	</div>

    我现在想每点击一次div1 下的 p 元素时,弹出 "paraX is clicked." 的提示框,为此,我们一般的做法就是给每一个p元素增加 相应的事件监听:

<script type="text/javascript">
	window.onload = function() {
		//添加事件监听
		document.getElementById("para1").addEventListener("click",eventPerformed);
		document.getElementById("para2").addEventListener("click",eventPerformed);
		document.getElementById("para3").addEventListener("click",eventPerformed);
		document.getElementById("para4").addEventListener("click",eventPerformed);
		document.getElementById("para5").addEventListener("click",eventPerformed);
	}
    //事件相应函数
	function eventPerformed(event){
		alert(event.target.id+" is clicked.");
	}
</script>

    是的,上述的代码完全可以实现上的功能。我们思考这个问题,如果这个div1 下有非常多个 p元素,我们总不能每一个都写上形如document.getElementById("paraX").addEventListener("click",eventPerformed);的代码片段吧,这样的话就太机械了!另外,如果在实际的应用中,很有可能同过js在 div1下动态生成p 元素,这时候,我们相应地还要添加事件处理函数,像这种动态添加的动作很有可能分散在我们 应用的很多个角落,这样动态添加处理函数将是一个非常蛋疼的事儿!

    解决方法: 利用 事件冒泡传递的机制,将本来本元素要完成的事件处理逻辑,委托给 父类节点,父类节点根据触发事件的节点信息,执行对应的事件处理逻辑。

<script type="text/javascript">
	window.onload = function() {
		//添加事件监听
		document.getElementById("box1").addEventListener("click",eventPerformed);
	}
    //事件相应函数
	function eventPerformed(event){
    	if(event.target.nodeName == 'P')
    	{
    		alert(event.target.id+" is clicked.");
    	}
	}
</script>

    通过上述的代码,就可以轻松搞定P 元素的事件处理函数绑定了,动态添加元素的时候,不需要再手动地绑定处理函数了。

可以看出,使用事件委托,可以简化了事件的处理逻辑,避免了多余的事件处理函数,进而节约了一定的内存。

    但是,事件委托也是有缺点的: 如果现在的dom 元素分为很多很多层,对于底层事件的委托,有可能在事件冒泡的过程中,中途被某个节点 终止冒泡了,这样事件就传递不到上层,则委托就会失败了。

jquery 对事件委托的支持

在jQuery里对事件委托的支持,有以下几个函数:

其中,live() 和die()、delegate()和undelegate() 是成对出现的,分别是绑定和解绑的过程。

delegate(selector,type,data,fn)

jquery 的delegate 方法是典型的为事件委托准备的。

看一下相应的定义:

delegate(selector,type,data,fn)

selector:选择器字符串,用于过滤器触发事件的元素。

type:     附加到元素的一个或多个事件。由空格分隔多个事件值。必须是有效的事件。

data:   传递到函数的额外数据

  fn:       当事件发生时运行的函数

概述:

         指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。

         使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)。

例如,我们将上面的例子用jquery实现:

<script type="text/javascript">
	$(function() {
                //让box1 处理来自 子元素P的click事件委托
		$("#box1").delegate("p", "click", function(event) {
			alert(event.target.id + " is clicked.");
		});
	})
</script>

       上述的代码实现了对box1 的子元素P 的click事件的委托处理。如果我们在js中动态地给box1 增加子元素P,相应的处理函数也会对其有效。

undelegate([selector,type,fn])

相应地,如果想取消对应的事件委托,可以使用以下代码:

$("#box1").undelegate("p","click");

delegate的使用方式是对某个元素的子元素进行事件委托处理,即形如:$("parentElement").delegate("siblings","eventType",function); parentElement元素作为一个冒泡事件处理的被委托者。jQuery还有另外一种方式:将元素的事件处理委托给DOM根节点来处理,这种方式是live()方式:

live(type, data, fn)

type   : 事件类型

data :附加的额外数据

fn   : 相应的处理函数

描述:jQuery 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。

备注: 自jQuery1.9后 就废除这个函数,只能在jQuery1.9以前的版本中使用。

将上述的功能用此方法实现:

<script type="text/javascript">
	$(function() {
		$("p").live("click",function(event) {
			alert(event.target.id + " is clicked.");
		});
	})
</script>
die(type, fn)

备注: 自jQuery1.9后 就废除这个函数,只能在jQuery1.9以前的版本中使用。

从元素中删除先前用.live()绑定的所有事件.(此方法与live正好完全相反。)如果不带参数,则所有绑定的live事件都会被移除。

与live() 相对应,取消绑定,则用下列代码:

$("p").die();

在事件绑定上,jQuery 提供了一种更通用的函数:

on(events,selector,data,fn)

参数:

events:一个或多个用空格分隔的事件类型和可选的命名空间,如"click"或"keydown.myPlugin" 。

selector:一个选择器字符串用于过滤器的触发事件的选择器元素的后代。如果选择的< null或省略,当它到达选定的元素,事件总是触发。

data:当一个事件被触发时要传递event.data给事件处理函数。

fn:该事件被触发时执行的函数。 false 值也可以做一个函数的简写,返回false。

将上述的功能改用on函数实现:

<script type="text/javascript">
	$(function() {
		$("#box1").on("click","p",function(event) {
			alert(event.target.id + " is clicked.");
		});
	})
</script>
off(events,selector,fn)

在选择元素上移除一个或多个事件的事件处理函数。off() 方法移除用.on()绑定的事件处理程序。

移除上面on 绑定的委托:

$("#box1").off("click","p");

在网上看到了关于 事件委托的总结,感觉挺不错的,就翻译一下贴在这里,跟大家分享一下,如有错误或纰漏,请指出。    点击我查看原文

总结:

    先决条件是要有一个容器,允许通用的事件处理函数。

   算法:

  1. 将事件处理函数绑定到容器上,
  2. 在事件处理函数内获取 event.target,
  3. 根据不同的event.target作相应的处理

应用场景:

  • 需要为子元素用一个事件处理函数 处理相同的动作;
  • 简化不同动作间的结构

优点:

  •  简化了初始化的过程,减少了多余的事件处理函数,进而节省了内存。
  •  简化了dom节点更新时,相应事件的更新
  • Allows to use innerHTML without additional processing.

缺点:

  • 第一,要求事件在IE中必须冒泡. 大多数的事件会冒泡,但是并不是所有的。对于其他的浏览器而言,捕获阶段也会同样适用。
  • 第二,理论上委托会导致浏览器额外的加载,因为在容器内的任意一个地方事件的发生,都会运行事件处理函数,所以多数情况下事件处理函数都是在空循环(没有意义的动作),通常不是什么大不了的事儿。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2014年04月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是委托?
  • 事件委托
  • jquery 对事件委托的支持
    • delegate(selector,type,data,fn)
      • undelegate([selector,type,fn])
        • live(type, data, fn)
          • die(type, fn)
            • on(events,selector,data,fn)
              • off(events,selector,fn)
              • 总结:
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档