目录
概述
“事件处理程序过多”问题的解决方案就是事件委托,利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
事件冒泡:由接收事件的元素开始,向上逐渐传播。比如页面结构为document->html->body->div,当点击div时,首先触发div的click事件,然后click事件向上传播,在每一级上都会发生,直至传播到document对象。
引入原因
事件处理程序过多,会导致整体页面的运行性能。首先,每个函数都是对象,都会占用内存,内存中的对象越多,性能就越差;其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
<ul id="myList">
<li id="item1">list item 1</li>
<li id="item2">list item 2</li>
<li id="item3">list item 3</li>
<li id="item4">list item 4</li>
</ul>
如上述程序,假设每个li都有click点击事件:
①不用事件委托:我们要一个个获取到每个li再对它们添加click事件,要添加四个事件处理程序。
②使用事件委托:只需要在父节点即ul节点上添加事件,这样就只需要取得一个DOM结点,只添加一个事件处理程序。
②相较于①,结果相同,但需要的内存更少。
具体写法
根据上述程序:
<!-- ①不用事件委托 -->
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");
var item4 = document.getElementById("item4");
item1.onclick = function(){
console.log("I am item1");
}
item2.onclick = function(){
console.log("I am item2");
}
item3.onclick = function(){
console.log("I am item3");
}
item4.onclick = function(){
console.log("I am item4");
}
<!-- 使用事件委托 -->
var myList = document.getElementById("myList");
myList.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
switch(target.id){
case "item1":
console.log("I am item1");
break;
case "item2":
console.log("I am item2");
break;
case "item3":
console.log("I am item3");
break;
case "item4":
console.log("I am item4");
break;
}
}
适用场景
多数鼠标事件和键盘事件。最适合采用该技术的事件有click,mousedown,mouseup,keydown,keyup,keypress,而mouseover和mouseout事件也冒泡,但由于经常需要计算元素位置,因而要适当处理它们并不容易。
本面试题为前端常考面试题,后续有机会继续完善。我是歌谣,一个沉迷于故事的讲述者。
欢迎一起私信交流。