事件委托也叫事件代理,其原理是利用事件冒泡来实现的,我们先看下面的代码
<div class="parent">
<div class="son">son 1</div>
<div class="son">son 2</div>
<div class="son">son 3</div>
<div class="son">son 4</div>
<div class="son">son 5</div>
<div class="son">son 6</div>
<div class="son">son 7</div>
<div class="son">son 8</div>
<div class="son">son 9</div>
<div class="son">son 10</div>
</div>
const s = document.querySelectorAll('.son')
for(let i = 0;i<s.length;i++){
s[i].addEventListener('click',(e)=>{
console.log('点击了son'+i)
})
}
若想判断是哪个儿子被点击了,则需要遍历每个son,然后给每一个son添加点击事件,那么这时候就要用到10个内存空间,但是加入是10000个或100000个son的时候,那么这将对内存占用率越来越大,自然性能就越差(这是因为js程序需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数就越多,然后就会延长整个页面的交互就需时间)。所以在这种情况下,假如我们只对父级对象进行操作的话,那么我们只需要一个内存空间就可以搞定了,这是因为在内部的元素执行监听函数的时候最后都会冒泡到外层在执行监听函数,所以我们只要对最外层的对象添加监听函数,内部的监听函数就都会触发,所以事件委托就是委托他们的父级代为执行事件
那么上面的代码用事件委托做又会怎么样呢,代码示例
const p = document.querySelector('.parent')
p.addEventListener('click',(e)=>{
const t =e.target
if(t.className.toLowerCase() === 'son')
console.log('点击了'+t.innerText)
})
我们可以看出用事件委托后,只用了一次dom操作就可以完成所有的效果,所以性能肯定比上面要好很多
那么假如要监听不存在元素的函数操作呢,这时候用事件委托就可以在在函数执行后判断是不是我们想要监听的元素,代码示例
const test = document.querySelector('.test')
setTimeout(()=>{
const button = document.createElement('button')
button.innerText ='button 1'
test.appendChild(button)
},1000)
test.addEventListener('click',(e)=>{
const t =e.target
if(t.tagName.toLowerCase()==='button')
console.log('点击了'+t.innerText)
})
由上面可以看出一开始button并不存在,那么如何监听button的函数操作呢,利用事件委托,判断是否是button被点击。
因此由上述两个案例可以看出,事件委托的优点为
- 节省内存
- 可以监听动态元素