- 事件委托,通俗地来讲,就是把一个元素响应事件(click、keydown、mousedown、mouseup、keyup、keypress)的函数委托到另一个元素;会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。
那么为什要用事件委托呢
- 在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
...
<li></li>
</ul>
- 每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤),比如有100个li标签,就要占用100个内存空间,如果是1000个,10000个呢,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象(ul)进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。
事件委托的原理
- 事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
如果还不理解的话,我们可以这样想,比如一个宿舍的同学同时快递到了,一种方法就是他们都傻傻地一个个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一一分发给每个宿舍同学;
在这里,取快递就是一个事件,每个同学指的是需要响应事件的 DOM 元素,而出去统一领取快递的宿舍长就是代理的元素,所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个。
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM事件委托</title>
</head>
<body>
<div id="container">
<button>按钮A</button>
<button>按钮B</button>
</div>
<!-- 习惯:把script代码块写到body的最后,因为script代码普遍比较大,写到后面不会影响前面的代码执行 -->
<script>
var buttons = document.querySelectorAll("button");
// 直接写事件
// buttons.forEach(function(button) {
// window.alert("Hi!");
// });
// 如果不利用 “事件委托” ,后添加的按钮在 监听事件 的后面,不会被事件监听
// buttons.forEach(function(button) {
// button.addEventListener("click", function(e) {
// window.alert("Hi!");
// });
// });
// var newButton = document.createElement("button");
// newButton.textContent = "按钮C";
// container.appendChild(newButton);
// 用 “事件委托” ,后添加的 按钮 仍然会被监听
var container = document.querySelector("#container");
container.addEventListener("click", function(e) {
window.alert("Hi!");
});
var newButton = document.createElement("button");
newButton.textContent = "按钮C";
container.appendChild(newButton);
</script>
</body>
</html>