本文已参与「[掘力星计划],赢取创作大礼包,挑战创作激励金。
小知识,大挑战!本文正在参与“[程序员必备小知识]创作活动。
前言
事件处理程序在现代web应用中可以实现交互,所以很多开发者会错误的在页面上大量使用他们。JavaScript中,页面的事件处理程序的数量与页面的整体性能是相挂钩的,甚至是息息相关的。原因其实有很多。首先,每个函数都是对象,都占用内存空间,也就是说对象越多,性能相对就越差。其次呢,为指定事件处理程序所需访问DOM的次数会先期造成整个页面交互的延迟。其实只要在使用事件处理程序时多注意一些方法,就可以改善页面性能。
事件委托
“过多事件处理程序”的解决方案就是使用事件委托。事件委托利用的是事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。
例如,click事件冒泡到document。这意味着可以为整个页面指定一个onclick事件处理程序,而不用为每个可点击元素分别指定事件处理程序。
<ul id= " myLinks">
<li id="gosomewhere">Go somewhere</li>
<li id="dosomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
对此,通常的做法是像这样指定3个事件处理程序(委托前):
let item1 = document .getElementById( "goSomewhere");
let item2 = document.getElementById( "doSomething");
let item3 =document.getElementById("sayHi");
item1 .addEventListener ("click",(event) =>{
location.href = "http:/l www.wrox.com";
});
item2.addEventListener( "click", (event) =>{
document .title = "Ichanged the document's title";
});
item3 .addEventListener("click", (event) =>{
console.log ("hi");
});
这样的结果就是所使用的onclick事件处理程序都如法炮制,出现大量雷同的指定事件处理程序的代码。使用事件委托,只要给所有元素的祖先节点添加一个处理程序就可以了。(委托后)
let list = document .getElementById( "mylinks");
list.addEventListener("cliCK", (event) =>{
let target = event.target;
switch(target.id) {
case "doSomething" :
document.title = "I changed the document 's title";
break;
case "goSomewhere":
location.href = "http:// www.wYOx.com";
break;
case "sayHi":
console. log ("hi");
break;
}
)};
这里只给ul元素添加了一个onclick事件处理程序。因为所有列表项都是这个元素的后代,所以它们的事件会向上冒泡,最终都会由这个函数来处理。但事件目标是每个被点击的列表项,只要检查event对象的id属性就可以确定,然后再执行相应的操作即可。相对于前面不使用事件委托的代码,这里的代码不会导致先期延迟,因为只访问了一个 DOM元素和添加了一个事件处理程序。结果对用户来说没有区别,但这种方式占用内存更少。所有使用按钮的事件(大多数鼠标事件和键盘事件)都适用于这个解决方案。
在许多情况下,只要行的通,我们就document只添加一个事件处理程序,通过它处理页面中所有某种类型的事件。
总结
-
document对象随时都使用,任意时刻都可以给他添加事件处理程序(不用等待DOMContentLoaded或者load事件)。意思就是说只要页面渲染出document,就可以没有延迟的起作用。
-
节省花在设置页面事件处理程序上的事件。因为只指定一个事件处理程序既能节省DOM引用,也可以处理时间。
-
最后一点,也是在一些我比较看重的一点,它减少了整个页面所需的内存,提升整体性能。
总的来说,事件委托最合适的事件有:click,mousedown,mouseup,keydown,keyup和keypress. mouseover和mouseout也可以使用,但是很难适当处理,而且经常需要计算元素位置。(因为mouseout会在光标从一个元素移动到它的后代节点以及移出元素之外触发)
注:下一章也是讲内存和性能的,讲的是删除事件处理程序(下一章详谈)