虽说事件处理程序可以为现代 Web 页面添加很强的交互能力,但是不分青红皂白就添加大量的事件处理程序绝对是一种愚蠢的行为。
我们来分析一下:事件处理程序本质上是一种函数,是一种对象,存放在内存中,设置大量的事件处理程序会使内存中的对象变多,Web 程序的性能会变得越来越差,用户体验很不好。
为了更好地利用好事件处理程序,便出现了事件委托,用来提升性能。
事件委托
事件委托(event delegation):把若干个子节点上的相同事件的处理函数绑定到它的父节点上去,在父节点上统一处理从子节点冒泡上来的事件,这种技术就叫做事件委托。
补充一下:事件委托并不局限于父节点与子节点之间。也可以这样玩,比如页面文档中有好多个处在不同位置地 button,都是绑定 click 事件,使用事件委托,我们可以把这些个事件统一绑定到 body 元素,然后再进行处理(虽然一般很少这么用)。
下面举例子逐步说明事件委托的优势:
<ul id="parent-list"> <li id="list-1">List 1</li> <li id="list-2">List 2</li> <li id="list-3">List 3</li> <li id="list-4">List 4</li> <li id="list-5">List 5</li> </ul>
假设有上面的代码,我们现在有一个需求:就是无论单击上面的列表(ul)的哪个子列表(li),都会弹出一个框,来显示我们点击了哪个子列表。
需求不难吧?有了需求,接下来是该写 js 代码了,现在有两种方法放在你眼前:1. 为每个 li 子元素绑定 click 事件,然后设置处理函数; 2. 利用事件委托,为 ul 父元素绑定 click 事件,然后设置处理函数
// 方法一 var list1 = document.getElementById("list-1"); list1.addEventListener("click",function(){ alert(this.firstChild.nodeValue); },false); var list2 = document.getElementById("list-2"); list2.addEventListener("click", function() { alert(this.firstChild.nodeValue); }, false); var list3 = document.getElementById("list-3"); list3.addEventListener("click", function() { alert(this.firstChild.nodeValue); }, false); var list4 = document.getElementById("list-4"); list4.addEventListener("click", function() { alert(this.firstChild.nodeValue); }, false); var list5 = document.getElementById("list-5"); list5.addEventListener("click", function() { alert(this.firstChild.nodeValue); }, false); // 方法二 var parentList = document.getElementById("parent-list"); parentList.addEventListener("click",function(){ var target = event.target; if(target.nodeName.toLowerCase() === "li"){ alert(target.firstChild.nodeValue); } },false);
看着上面的代码,我这里写几点方法二的优点:1. 减少了访问 DOM 的次数,提升了性能;2. 将子元素的事件处理程序统一绑定到其父元素,减少了对内存的占用;3. 可以更好地管理事件处理程序,比如移除对某个事件处理程序的引用
注意:如果对各个子元素的需求不一样,我们还可以这样来改写上面的方法二:
// 方法二 var parentList = document.getElementById("parent-list"); parentList.addEventListener("click",function(){ var target = event.target; if(target.nodeName.toLowerCase() === "li"){ switch(target.id){ case "list-1": alert("学的越多,越觉得自己无知!"); break; case "list-2": alert("爱是一种艺术!"); break; case "list-3": target.innerHTML = "呵呵,我改了啊!"; break; case "list-4": target.style.background = "#aaa"; break; case "list-5": target.style.color = "red"; target.style.fontSize = "2em"; break; default: break; } } },false);
因为事件委托依赖事件冒泡机制,所以,并不是所有的事件都可以进行事件委托。
最适合采用事件委托的事件包括:click、mousedown、mouseup、keydown、keyup 和 keypress。
事件委托只是一种非常不错的事件绑定的思想,所以不应该拘泥于上面的例子,要活学活用! ^_^
移除事件处理程序
我们前面说过,事件处理程序存在于内存中,每当将事件处理程序指定给元素时,运行中的浏览器代码与支持页面交互的 JavaScript 代码之间就会建立一个连接。这种连接越多,页面执行就越慢。前面所说的事件委托就是用来限制建立的连接数量。
还有,就是内存中那些使用完后不再使用的事件处理程序,如果不释放掉,也会影响 Web 应用程序的内存和性能。
<button id="button">提交</button> var button = document.getElementById("button"); button.onclick = function(){ // 提交某个表单的操作代码 button.onclick = null; // 移除事件处理程序 event.target.firstChild.nodeValue = "提交中。。。"; };
总的原则就是:移除掉那些过时不再使用的事件处理程序,释放内存!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持小牛知识库!
事件 事件:用户与浏览器特定的交互瞬间。 内存和性能 事件处理程序为现代web浏览器提供了交互能力,但有时也不能一味地为页面添加事件处理程序,在JavaScript中,添加到页面中的事件处理程序的数量直接影响着页面整体的运行性能。添加到页面中的事件处理程序越多,那么所占用的内存也多,运行性能就会下降。而且事先指定事件处理程序面导致的DOM访问次数也会增多。对于如何利用好事件处理程序对页面运行性能的
问题内容: 运行时,我看到了一系列的 硬件缓存事件 ,如下所示: 这些事件似乎大多基于测试返回合理的值,但是我想知道如何确定将这些事件映射到系统上的硬件性能计数器事件? 也就是说,这些事件肯定是在Skylake CPU上使用一个或多个基础x86 PMU计数器实现的-但是我怎么知道哪个? 您可以查找其他硬件事件,但不能查找“硬件缓存事件”。 问题答案: 用户@Margaret指出注释中的合理答案-阅
虚拟内存是一种方便的方法,可以在进程之间隔离内存,并为每个进程提供自己的地址空间。它通过将虚拟地址转换为物理地址来工作。 我已经非常熟悉虚拟内存的工作原理和实现。我不知道的是虚拟内存相对于直接映射内存的性能影响,直接映射内存不需要翻译开销。 请不要说没有开销。这显然是错误的,因为遍历页表需要多次内存访问。TLB未命中可能很少,因此对性能的影响可以忽略不计,但是,如果是这种情况,应该有证据证明这一点
由于事件处理程序可以为现代Web 应用程序提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序。在创建GUI 的语言(如C#)中,为GUI 中的每个按钮添加一个onclick事件处理程序是司空见惯的事,而且这样做也不会导致什么问题。可是在JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能。导致这一问题的原因是多方面的。首先,每个函数都是对象,
问题内容: 我有这个JavaWeb应用程序,它可以从电子表格上传成千上万的数据,该电子表格是从上到下按行读取的。我用来在服务器端显示应用程序当前正在读取的行。 -我知道要创建一个日志文件。实际上,我正在创建一个日志文件,同时在服务器提示符下显示日志。 还有其他方法可以在提示上打印当前数据? 问题答案: 它可能会影响您的应用程序性能。大小会因您所运行的硬件类型和主机上的负载而异。 可以将其转化为性能
前言 HTTPS 在保护用户隐私,防止流量劫持方面发挥着非常关键的作用,但与此同时,HTTPS 也会降低用户访问速度,增加网站服务器的计算资源消耗。 本文主要介绍 https 对用户体验的影响。 HTTPS 对访问速度的影响 在介绍速度优化策略之前,先来看下 HTTPS 对速度有什么影响。影响主要来自两方面: 协议交互所增加的网络 RTT(round trip time)。 加解密相关的计算耗时。