一、什么是事件委托
提到事件委托,我们必须先了解事件流中的事件捕获和事件冒泡。
事件捕获就是从DOM的根元素开始去执行对应的事件,执行过程是从外到里。
事件冒泡就是从文档树中最深的节点开始触发,然后向上传播至没有那么具体的文档,执行过程是从里到外。
<ul>
<li>first child</li>
</ul>
<script>
const li = document.querySelector('li')
const ul = document.querySelector('ul')
const body = document.body
li.addEventListener('click', function () {
console.log('我是子元素')
})
ul.addEventListener('click', function () {
console.log('我是父元素')
})
body.addEventListener('click', function () {
console.log('我是body')
})
document.addEventListener('click', function () {
console.log('我是document')
})
</script>
效果如下:
当我点击子元素的时候,就触发了事件冒泡机制,从 li 开始触发到 ul 再到 body 最后到 document。
而事件委托就是利用事件冒泡,把原本要绑定在子元素的响应事件委托给父元素,通过父元素监听子元素。
二、使用场景
当我们要给n个按钮添加点击事件时,最笨的方法就是给每个按钮都添加,此方法耗时且麻烦。但是如果委托给父元素,让父元素担当事件监听的职务,则通过事件冒泡就可以获取到所有子元素。
<ul>
<li>first child</li>
<li>second child</li>
<li>third child</li>
<li>fourth child</li>
<li>fifth child</li>
</ul>
<script>
// 点击每个小li 被点击的li消失
// 1. 获得父元素
const ul = document.querySelector('ul')
// 2. 利用事件委托,将点击事件委托给父元素
ul.addEventListener('click', function (e) {
// e.target: 判断点的是哪一个元素(标签)
// tagName: 标签名字
// 3. 找到触发的元素
if (e.target.tagName === 'LI') {
e.target.style.display = 'none'
}
})
</script>
效果如下:
其中,e.target 是事件源,获取 e.target 以查看事件实际发生的位置并进行处理;tagName 是标签名字,注意必须得大写。
三、优点
- 减少事件注册的次数,节省内存占用,提高程序的性能
- 新增子对象时也无需再次对其绑定