我们知道js的事件机制存在捕获和冒泡, 一般来说,如果我们只希望事件只触发在目标上,这时候可以使用 stopPropagation 和 stopImmediatePropagation 来阻止事件的进一步传播。
stopPropagation
stopPropagation 的功能是阻止事件传播,包括阻止捕获或冒泡,之前错误的认为只是阻止事件冒泡的。
我们来看一个例子:
<div id="one">
<div id="two">
<div id="three">3</div>
</div>
</div>
<style>
div{
border: 1px solid #111;
padding: 20px;
}
</style>
<script>
const one = document.querySelector('#one')
const two = document.querySelector('#two')
const three = document.querySelector('#three')
one.addEventListener('click', (e) => {
console.log('捕获: 1')
}, true)
one.addEventListener('click', (e) => {
console.log('冒泡: 1')
}, false)
two.addEventListener('click', (e) => {
console.log('捕获: 2')
}, true)
two.addEventListener('click', (e) => {
console.log('冒泡: 2')
}, false)
three.addEventListener('click', (e) => {
console.log('捕获: 3')
}, true)
three.addEventListener('click', (e) => {
console.log('冒泡: 3')
}, false)
</script>
点击3, 打印结果如下,这是完整的捕获和冒泡流程:
捕获: 1
捕获: 2
捕获: 3
冒泡: 3
冒泡: 2
冒泡: 1
我们在2的捕获阶段stopPropagation:
two.addEventListener('click', (e) => {
e.stopPropagation()
console.log('捕获: 2')
}, true)
点击3, 打印结果如下,事件流在捕获阶段就被阻止了:
捕获: 1
捕获: 2
我们在2的冒泡阶段stopPropagation:
two.addEventListener('click', (e) => {
e.stopPropagation()
console.log('冒泡: 2')
}, false)
点击3, 打印结果如下:
捕获: 1
捕获: 2
捕获: 3
冒泡: 3
冒泡: 2
stopImmediatePropagation
stopImmediatePropagation 同样也能实现阻止事件传播, 它与 stopPropagation 的区别是: 还能阻止该监听函数之后注册的监听函数。
我们来看一个例子:
<div>
<p>paragraph</p>
</div>
<script>
const p = document.querySelector('p')
p.addEventListener("click", (event) => {
alert("我是p元素上被绑定的第一个监听函数");
}, false);
p.addEventListener("click", (event) => {
alert("我是p元素上被绑定的第二个监听函数");
event.stopImmediatePropagation();
// 执行stopImmediatePropagation方法,阻止click事件冒泡,并且阻止p元素上绑定的其他click事件的事件监听函数的执行.
}, false);
p.addEventListener("click",(event) => {
alert("我是p元素上被绑定的第三个监听函数");
// 该监听函数排在上个函数后面,该函数不会被执行
}, false);
document.querySelector("div").addEventListener("click", (event) => {
alert("我是div元素,我是p元素的上层元素");
// p元素的click事件没有向上冒泡,该函数不会被执行
}, false);
</script>