文章目录
一、什么是事件捕获和事件冒泡
事件机制是指当特定的操作(如点击按钮、移动鼠标等)在DOM元素上发生时,会触发相应的事件。JavaScript通过监听事件并绑定对应的处理函数来响应用户的操作,对用户的交互做出响应。
1.1、事件冒泡
如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发
元素->父元素->body->html->document->window
事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
1.2、事件捕获
从最顶级的父元素一级一级往下找子元素触发同名事件,直到触发事件的元素为止
事件捕获,只能通过addEventListener
并且参数写true
才是事件捕获
其他都是冒泡(不是通过addEventListener
添加、addEventListener
参数为false
)
事件对象的stopPropagation
方法除了可以阻止冒泡还可以阻止捕获
二、事件流
事件流分为三个阶段
1.捕获阶段
2.目标阶段
3.冒泡阶段。
三、addEventListener
JavaScript
中,我们可以使用addEventListener
方法来绑定捕获和冒泡事件。
element.addEventListener(event, function, useCapture);
其中,
event
表示要绑定的事件类型,function
表示事件触发时要执行的函数,useCapture
是一个可选的参数,用于指定事件是使用捕获还是冒泡阶段进行处理。
当useCapture
为false
或未提供时,事件将在冒泡阶段进行处理;当useCapture
为true
时,事件将在捕获阶段进行处理此时事件不在冒泡,只捕获不冒泡。
<div id="blueBox">
<div id="yellowBox">
<div id="greenBox"></div>
</div>
</div>
<script>
let blueBox = document.getElementById('blueBox');
let yellowBox = document.getElementById('yellowBox');
let greenBox = document.getElementById('greenBox');
blueBox.addEventListener('click', () => {
console.log('blueBox')
})
yellowBox.addEventListener('click', () => {
console.log('yellowBox')
})
greenBox.addEventListener('click', () => {
console.log('greenBox');
})
</script>
当点击绿色方块时,输出
greenBox、yellowBox、blueBox
,因为绿色包含在黄色里,黄色和绿色被包含蓝色中。addEventListener
不写第三个参数时,事件将在冒泡阶段进行处理,从目标元素开始,逐级向外层元素传播,直到达到最外层的元素,也就是绿色、黄色、蓝色。
同理,点击黄色时,输出
yellowBox、blueBox
。点击蓝色时,输出blueBox
。
如果将第三个参数全部设成true,点击绿色(greenBox),将输出blueBox、yellowBox、greenBox,因为事件将在捕获阶段进行处理,事件捕获的顺序是从最外层的元素开始,逐级向内部元素传播,直到达到目标元素,也就是蓝色、黄色、绿色。
四、阻止事件冒泡
4.1、event.stopPropagation()
调用该方法会阻止事件继续传播,但不会阻止其他事件处理程序被触发。也就是说,如果一个元素上绑定了多个事件处理程序,调用该方法只会阻止事件传播到更高层级的元素,而不会阻止同一元素上的其他事件处理程序被触发。
blueBox.addEventListener('click', () => {
console.log('blueBox')
}, true);
yellowBox.addEventListener('click', () => {
console.log('yellowBox')
})
greenBox.addEventListener('click', (event) => {
console.log('greenBox');
event.stopPropagation();
}, true);
在上面的示例中,当点击绿色方块时,调用
event.stopPropagation()
会阻止事件继续传播到外层元素,所以只会输出"greenBox",而不会输出”yellowBox”和”blueBox”。
四、事件委托
事件委托也称为事件代理(Event Delegation),事件委托是一种将事件处理程序绑定到一个父元素上,而不是将事件处理程序绑定到每个子元素上的技术。通过事件委托,可以减少事件处理程序的数量,提高性能和代码的可维护性。
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
let li = document.getElementsByTagName("li");
for (let i = 0; i < li.length; i++) {
li[i].addEventListener("click", () => {
console.log(li[i].innerHTML);
});
}
</script>
如上述代码所示,点击某一数字,就会输出对应内容。节点少的时候还好,如果节点多达上千上万个,就需要声明相当多的事件函数,比较消耗内存。而且如果列表经常发生动态变更,也会导致大量监听事件的移除和绑定。
在这种情况下,事件委托就可以体现它的优势了。事件委托正是利用事件流的冒泡特性,将本来要绑定到多个元素的事件函数,委托到了其祖先元素上。
优点:节约内存 提升性能(不需要注销子节点)
//事件代理 节约内存 提升性能(不需要注销子节点)
let ul = document.getElementById("ul");
ul.addEventListener("click", (event) => {
console.log(event.target.innerHTML);
})
我们通过将事件处理程序绑定到父元素ul上,当点击列表项时,通过
event
对象拿到必要的信息,会打印出被点击的列表项的内容。如此这般,不管li
有多少,更新多频繁,我们只需要维护一个函数就够了。