前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单说 JavaScript中的事件委托(上)

简单说 JavaScript中的事件委托(上)

作者头像
FEWY
发布2019-05-26 12:00:02
5640
发布2019-05-26 12:00:02
举报
文章被收录于专栏:FEWYFEWY

版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。 https://blog.csdn.net/FE_dev/article/details/78821578

说明

这篇文章说JavaScript中的事件委托,这次先说一些比较基本的知识。

事件委托 是什么

先来看看事件委托的概念

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

事件委托,你叫他 事件代理 也可以,都是一个意思。 事件:JavaScript 侦测到的行为就是事件,比如鼠标点击、某个键盘的键被按下、元素获得焦点。 委托:就是把原来自己做的事,交给别人做。

事件委托 的原理

要说事件委托的原理,我们应该先明白事件冒泡

事件冒泡:从目标元素出发,向外层元素冒泡,最后到达顶层(window或document),依次执行绑定在其上的事件。

我们来看段代码

代码语言:javascript
复制
<!doctype html>
<html lang="en">
 <head>
    <style>
		div{
		   width:100px;
		   height:100px;
		   background:red;
		}
		p{
		   width:50px;
		   height:50px;
		   background:blue;
		}
	</style>
 </head>
 <body>

    <div id='div'>
		<p id='p'></p>
	</div>

	<script>
		p.onclick = function (){
			console.log('蓝色 p 元素 触发事件');
		}
		div.onclick = function (){
			console.log('红色 div 元素 触发事件');
		}
	</script>
 </body>
</html>

效果图

这里写图片描述
这里写图片描述

从上面的图中我们看见,当点击 蓝色 p 元素时,先触发了 p 元素上绑定的事件,然后又触发了 红色 div 元素上绑定的事件,这就是事件冒泡了。

事件委托 的实现

先来段代码

代码语言:javascript
复制
<!doctype html>
<html lang="en">
 <head>
 </head>
 <body>
    <ul id='ul'>
		<li id='li1'>1</li>
		<li id='li2'>2</li>
	</ul>

	<script>
	   //分别给每个 li 元素,绑定单击事件
	   li1.onclick = function (){
			console.log(li1.innerHTML);
	   }
	   li2.onclick = function (){
			console.log(li2.innerHTML);
	   }
	</script>
 </body>
</html>

我们用事件委托的方式改写一下上面的代码,不过在这之前,我们还要明白一下什么是 event 对象

任何事件触发后将产生一个event对象 event对象记录事件发生时的鼠标位置、键盘按键状态和 触发对象等信息 一般情况下,绑定事件处理函数时,event对象默认以第一个参数方式传入

event对象有许多的属性,具体的可以到这里去看 http://www.w3school.com.cn/jsref/dom_obj_event.asp

如果用事件委托,那代码就是这样的

代码语言:javascript
复制
<!doctype html>
<html lang="en">
 <head>
 </head>
 <body>
    <ul id=ul>
		<li id='li1'>1</li>
		<li id='li2'>2</li>
	</ul>

	<script>
	   //用事件委托,给父元素 ul 绑定单击事件
	   ul.onclick = function (e){
		   //这里的e 就是event对象
		   
		   //target属性 返回触发此事件的元素(事件的目标节点)
		   //nodeName 属性 返回指定节点的节点名称(返回的标签名是大写)
		  if(e.target.nodeName == 'LI'){
			console.log(e.target.innerHTML);
		  }
	   }
	</script>
 </body>
</html>

上面的代码,应该很容易看懂的,我们看看他们的区别 1、第一段代码是在 每个 li 上绑定事件,第二段只是在 li 的父元素 ul 上绑事件。 2、第一段绑定了两次事件,第二段绑定了一次事件

也就是说,原来在 li 上绑定的事件,现在委托在了父元素 ul 上,而在 ul 上只需要绑定一次就可以了。

我们再来看另一种情况,当元素最开始不存在时,需要绑定事件,最先能想到会出现这种情况的场景就是,元素是通过发请求,获取数据后,拼接到页面上的。而这种元素如果在发请求之前就绑定事件,是不会生效的。

代码语言:javascript
复制
<!doctype html>
<html lang="zn">
 <head>
 </head>
 <body>
    <ul id=ul>
		<li id='li1'>1</li>
		<li id='li2'>2</li>
	</ul>

	<script>
		// 元素还不存在时,就绑定事件
		var li3 = document.getElementById("li3");
		li3.onclick = function (){
			console.log(li3.innerHTML);
		}
		// 定时器 1秒后创建元素 li3
		setTimeout(function(){
			var li3 = document.createElement("li");
			li3.setAttribute("id","li3"); 
			li3.innerHTML = "3";
			var ul = document.getElementById("ul");
			ul.appendChild(li3);
		},1000)
	</script>
 </body>
</html>

上面这段代码中,在元素 li3 还不存在的时候就绑定事件了,所以执行代码后就会报错

在这里插入图片描述
在这里插入图片描述

解决这个问题最直接的办法就是等元素添加到页面上之后,再绑定事件,我们来改改代码。

代码语言:javascript
复制
<!doctype html>
<html lang="zn">
 <head>
 </head>
 <body>
    <ul id=ul>
		<li id='li1'>1</li>
		<li id='li2'>2</li>
	</ul>

	<script>
		// 定时器 1秒后创建元素 li3
		setTimeout(function(){
			var li3 = document.createElement("li");
			li3.setAttribute("id","li3"); 
			li3.innerHTML = "3";
			var ul = document.getElementById("ul");
			ul.appendChild(li3);

			// 元素添加到页面上之后,再绑定事件
			var li3 = document.getElementById("li3");
			li3.onclick = function (){
				console.log(li3.innerHTML);
			}
		},1000)
	</script>
 </body>
</html>

改成这样后,绑定事件就可以起作用了,但是这样如果元素改变多次,就要元素渲染一次,就绑定一次事件,显然是有点麻烦了。

我们用事件委托的方式,再来改改。

代码语言:javascript
复制
<!doctype html>
<html lang="zn">
 <head>
 </head>
 <body>
    <ul id=ul>
		<li id='li1'>1</li>
		<li id='li2'>2</li>
	</ul>

	<script>
	   //用事件委托,给父元素 ul 绑定单击事件
	   ul.onclick = function (e){
		   //这里的e 就是event对象
		   
		   //target属性 返回触发此事件的元素(事件的目标节点)
		   //nodeName 属性 返回指定节点的节点名称(返回的标签名是大写)
		  if(e.target.nodeName == 'LI'){
			console.log(e.target.innerHTML);
		  }
	   }
		// 定时器 1秒后创建元素 li3
		setTimeout(function(){
			var li3 = document.createElement("li");
			li3.setAttribute("id","li3"); 
			li3.innerHTML = "3";
			var ul = document.getElementById("ul");
			ul.appendChild(li3);
		},1000)
	</script>
 </body>
</html>

上面这段代码,我们用事件委托的方式,并不在生成的元素上绑定事件,而是在生成元素的父元素上绑定事件,因为父元素是一直存在的,所以绑定的事件就可以生效。

事件委托 的好处

1、减少了事件监听器,原来需要在多个子元素绑定相同的事件处理函数,现在只需要在祖先元素(一般为父元素)上统一定义一次即可。

2、减少内存消耗,提高了页面性能,这主要还是减少了事件处理函数的数量

3、动态绑定事件,比如我们需要增加一个元素,那么我们还需要重新给这个元素绑定事件,但是用事件委托就没关系了,因为事件 不是 绑定在目标元素上的,而是绑定在已经存在于页面上的父元素,冒泡到父元素上时,执行绑定在父元素上的事件处理函数,这样能减少很多不必要的工作。

事件委托 的局限

focus、blur 之类的事件本身没有事件冒泡机制,所以无法委托; mousemove、mouseout 这样的事件,虽然有事件冒泡,但是每次都要计算它的位置,对性能消耗高,而且很麻烦,因此也是不适合用事件委托。

总结

这篇文章是比较基础的,还有一些东西没有说,比如文中说 事件委托的实现 的时候,举的例子比较简单,监听的 li 里面没有子元素,如果存在子元素时,那点击子元素 事件就不会触发,那怎么办呢? 还有 JQuery中的事件委托 又是怎么做的呢? 看这里

简单说 JavaScript中的事件委托(下)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年12月17日,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 说明
  • 事件委托 是什么
  • 事件委托 的原理
  • 事件委托 的实现
  • 事件委托 的好处
  • 事件委托 的局限
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档