摘要:网上有关于事件委托的一个取快递例子,十分生动,这里我对它作一些修改和拓展,然后通过程序来说明事件委托的机制。还有一个优点当增加新的节点时,自动携带父元素的事件效果。以上便是事件委托的基本思想。与其对应的还有事件捕获。
事件委托(又名事件代理),就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
网上有关于事件委托的一个“取快递”例子,十分生动,这里我对它作一些修改和拓展,然后通过程序来说明事件委托的机制。
某公司有三位员工,他们的快递收件地址为公司,每当有快递送达时,快递员拨打其电话进行通知,他们接到电话后去取件。
员工ID | 员工名称 | 联系方式 |
---|---|---|
A | 甲 | 111111 |
B | 乙 | 222222 |
C | 丙 | 333333 |
对应到页面,就是每个员工是一个标记:
每位员工接电话取快递的行为就是一个个事件,这里我们假设收取快递行为对应着onclick事件:
A.onclik = function() { 收取快递; }; B.onclick = function() { 收取快递; }; C.onclick = function() { 收取快递; };
以上的实现,通常为通过循环遍历每一个员工,为其增加事件:
/*程序1*/ var aUl = document.getElemengtByID("前台工作人员"); var aLi = aUl.getElemengtsByTagName("li"); for (var i = 0; i < aLi.length; i++) { aLi[i].onclick = function() { 收取快递; } }
可以看到,为每个员工都设置一个事件,会产生冗余代码,占用内存,同时会进行多次DOM操作(与DOM节点进行交互),影响页面运行性能。
“减少DOM操作是性能优化的主要思想之一”
于是,我们理所当然地想到:为什么不能让前台工作人员帮我们签收快递呢?
假设此时快递员打电话通知员工甲取件(onclick),但员工甲的DOM节点
可以看到,这样一来,不仅缩减代码量,同时与DOM节点的交互次数也得到了缩减。
还有一个优点:当增加新的DOM节点时,自动携带父元素的事件效果。也就是说,当有一个新员工丁来公司后,前台工作人员会直接帮他收取快递,而无需专门为他设置事件。
例如,当新员工丁来到公司后:
... ... ... /*程序3*/ var aBtn = document.getElementById("btn"); aBtn.onclick = function() { var aLi = document.createElement("li"); oLi.innerHTML = "员工丁"; aUl.appendChild(aLi); } ...
在不使用事件委托的程序中,新增的员工丁是没有事件的,我们需要用一个函数包含住程序1:
/*程序4*/ function pro1() { var aUl = document.getElemengtByID("前台工作人员"); var aLi = aUl.getElemengtsByTagName("li"); for (var i = 0; i < aLi.length; i++) { aLi[i].onclick = function() { 收取快递; } } }
然后在新增新员工丁的程序的末尾执行这个函数:
/*程序5*/ var aBtn = document.getElementById("btn"); aBtn.onclick = function() { ... pro1(); }
这样做的缺点是显而易见的:DOM节点交互次数成倍增加。
若我们采用事件委托机制来实现,就不会存在这个问题,子元素节点的onclick事件会直接在父元素节点得到执行。
到这里,我们会想到:对于同一种事件来说,使用事件委托将其放置在父元素节点上固然很方便。但如果对于不同的子元素节点要执行不同的事件呢,还能使用事件委托吗?
答案是肯定的。
例如上述三位公司员工,总是使用固定品牌的快递:
员工甲因为便宜,喜欢使用申通快递,申通只送到园区大门;
员工乙是京东会员,总是购买京东自营商品,京东快递送到楼下;
员工丙是顺丰VIP,顺丰快递会送到送到所在楼层大厅。
他们三位在接到电话后,前台工作人员需要去不同的地方取件,对于不使用事件委托的程序,需要对每个人设置独特的处理事件:
var A = document.getElementById("A"); var B = document.getElementById("B"); var C = document.getElementById("C"); A.onclick = function() { 去园区大门取快递; } B.onclick = function() { 去楼下取快递; } C.onclick = function() { 去本层大厅取快递; }
至少需要三次DOM操作,而且为每一个对应节点都设置了事件函数。
而若采用事件委托:
var aUl = document.getElementByID("前台工作人员"); aUl.onclick = function (ev) { var target = ev.target || ev.srcElement; /*兼容浏览器*/ if (target.nodeName.toLocaleLowerCase() == "li") { switch(target.id) { case "A" : 去园区大门取快递; break; case "B" : 去楼下取快递; break; case "C" : 去本层大厅取快递; break; } } }
这样一来,DOM操作就只有一次,其他的操作都在JS内进行,可以有效提升网页性能。
以上便是JS事件委托的基本思想。简而言之,就是利用事件冒泡这一特点,来对事件进行管理,减少冗余代码,减少不必要的创建,减少交互操作以节约内存和提高性能。
事件冒泡是当触发某个DOM元素节点时,若该节点没有对应事件,则检查其父元素是否有对应事件,若有,则执行,若没有,继续向上检查。与其对应的还有事件捕获。
关于事件流的具体分析,将在以后的文章中总结。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102543.html
摘要:见下图更直观在事件流中,事件的目标在捕获阶段不会接受到事件,这意味着在捕获阶段,事件从到后就停止了。下一个阶段是目标阶段,于是事件在上发生,并在事件处理中被看成是冒泡阶段的一部分,然后,冒泡阶段发生,事件又传回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕获 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是从页面中接受事件的顺序 2.DOM事件流的三个阶...
摘要:见下图更直观在事件流中,事件的目标在捕获阶段不会接受到事件,这意味着在捕获阶段,事件从到后就停止了。下一个阶段是目标阶段,于是事件在上发生,并在事件处理中被看成是冒泡阶段的一部分,然后,冒泡阶段发生,事件又传回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕获 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是从页面中接受事件的顺序 2.DOM事件流的三个阶...
摘要:见下图更直观在事件流中,事件的目标在捕获阶段不会接受到事件,这意味着在捕获阶段,事件从到后就停止了。下一个阶段是目标阶段,于是事件在上发生,并在事件处理中被看成是冒泡阶段的一部分,然后,冒泡阶段发生,事件又传回。 CONTENTS DOM事件流 事件冒泡 阻止冒泡 事件捕获 事件委托 DOM事件流 1.什么是事件流? 事件流所描述的是从页面中接受事件的顺序 2.DOM事件流的三个阶...
摘要:案例说明使用原生完成桌面操作级应用,对于原生的掌握情况而言,是一个较为全面的综合型案例。本次课从事件相关的功能入手,给大家带来详细的分享。 showImg(https://segmentfault.com/img/bVbh1qw); 案例说明:使用原生 JS 完成桌面操作级应用,对于原生 JS 的掌握情况而言,是一个较为全面的综合型案例。本次课从事件(event)相关的功能入手,给大家...
摘要:本文是重温基础系列文章的第二十篇。事件捕获为截获事件提供机会,然后实际的目标接收到事件,最后事件冒泡,对事件作出响应。事件处理事件处理,即响应某个事件。包括导致事件的元素事件类型等其他信息。 本文是 重温基础 系列文章的第二十篇。 这是第三个基础系列的第一篇,欢迎持续关注呀! 重温基础 系列的【初级】和【中级】的文章,已经统一整理到我的【Cute-JavaScript】的Java...
阅读 1299·2021-09-24 10:26
阅读 3633·2021-09-06 15:02
阅读 571·2019-08-30 14:18
阅读 554·2019-08-30 12:44
阅读 3101·2019-08-30 10:48
阅读 1914·2019-08-29 13:09
阅读 1975·2019-08-29 11:30
阅读 2258·2019-08-26 13:36