事件冒泡和事件捕获
事件触发顺序
<div id="div1">
<div id="div2"></div>
</div>
当DOM出现上面这种嵌套的层级关系时,如果父级元素和子级元素同时绑定了DOM事件(例如点击事件),那事件触发的顺序是怎样的?当点击div2
时,是div2
绑定的点击事件先执行还是div1
?
为了解决这个问题,事件冒泡和事件捕获的概念被提出。
事件冒泡
微软提出了事件冒泡
的概念,事件冒泡即事件会被由下至上
(或者说由内至外
)进行传递,如同水里的泡泡一直向上浮起,直至最外层。
let div1 = document.getElementById('div1')
let div2 = document.getElementById('div2')
div1.addEventListener('click', function(e) {
console.log('div1')
}, false) // useCapture为false
div2.addEventListener('click', function(e) {
console.log('div2')
}, false)
当div1
定义点击事件并且设置冒泡时,此时点击元素div2
,事件由下至上开始,打印结果为:先div2再div1
。
addEventListener的第三个参数表示
是否使用捕获
,设置false表示不使用捕获而使用冒泡。
可以通过e.stopPropagation()
阻止冒泡
事件捕获
事件捕获
由网景公司提出,事件捕获与事件冒泡的行为完全相反,事件会被由上至下
(或者说由外至内
)进行传递。
let div1 = document.getElementById('div1')
let div2 = document.getElementById('div2')
div1.addEventListener('click', function(e) {
console.log('div1')
}, true) // useCapture为true
div2.addEventListener('click', function(e) {
console.log('div2')
}, false)
当div1
定义点击事件并且设置捕获时,此时点击元素div2
,事件由上至下开始,打印结果为:先div1再div2
。
事件代理
日常开发中我们往往会给列表中的每个列表项绑定事件,当列表变得比较大时遍历列表绑定的事件也就越多,导致性能下降。
<ul id="ul">
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
let items = document.querySelectorAll('#ul li')
for (let index = 0; index < items.length; index++) {
items[index].onclick = function(e) {
console.log(e.target.innerHTML)
}
}
此时可以通过只给列表的父级元素绑定事件,点击子级元素时会冒泡到父级元素,再通过e.target
获取到点击的目标元素,这样相当于把多个事件合并成一个,从而达到优化的作用。
let ul = document.querySelector('#ul')
ul.onclick = function(e) {
console.log(e.target.innerHTML)
}
转载自:https://juejin.cn/post/7265130379966758967