由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方法叫做事件的代理.一般多用作需要在多个子元素身上绑定相同的监听事件的时候使用.
为什么要使用事件委托:
一般来说dom需要有事件处理程序,我们直接为他设置事件处理程序即可.如果遇到很多的dom需要添加事件处理程序这样做就会产生很多影响.
例如我们要给100个li添加点击事件,可以使用for循环.
<ul>
<li>0</li>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
let liArr = document.querySelectorAll("li");
for(let i=0; i<liArr.length; i++){
liArr[i].addEventListener("click",()=>{
console.log(i)
})
}
但是如果由1000个10000个甚至更多,这将会直接影响到页面的整体运行性能,监听函数越多,就越占用内存(函数也是对象),使用事件委托,我们只需要对父级这一个对象进行操作,即只需要一个内存空间就可以了,从而大大节省内存.
let ul = document.querySelector("ul")
ul.addEventListener("click",(e) => {
if(e.target.tagName.toLocaleLowerCase() === "li"){
console.log(e.target.value)
}
})
另外,如果此时要往ul里面添加一个li,并为其绑定监听事件,上述方法就可以直接解决,能做到监听动态元素.
当然事件委托也有缺点:
-
事件委托基于冒泡,对于不冒泡的事件不支持;
-
层级过多,冒泡过程中可能会被某层阻止掉;
-
理论上委托会导致浏览器频繁调用处理函数,有些可能不需要处理,多以一般委托要就近委托;
-
所有的事件都是用委托会出现事件误判,比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。
综上
click,mousedown,mouseup,keydown,keyup,keypress这些事件适合使用事件委托.虽然mouseover和mouseout也有事件冒泡,但是他们需要经常计算它们的位置,处理起来不太容易。
参考文章:
[https://juejin.cn/post/6844903589052153869](https://juejin.cn/post/6844903589052153869)