很多人粗略地认为该属性只是阻止冒泡,实际上,正如其英文含义所示,它只是用来阻止事件传播,不管是事件冒泡阶段还是事件捕获阶段都可阻止进一步传播。首先要明确,每个元素既可设置捕获事件,也可设置冒泡事件,当然,该事件必须具备这样的特性,比如click事件。设置捕获和冒泡主要是设置capture选项,设置为true则是捕获,否则是冒泡(默认)。此外,对于一个元素来说,捕获事件永远先于冒泡事件触发,捕获事件总是从该元素的外层元素向内传递,而冒泡事件恰好相反。
首先来看这样一个例子:
<div id="out" style="width:80px;height:60px;background:#fe2375;">
<div id="in" style="width:60px;height:40px;background:#a146f3;"></div>
</div>
<script>
const outdiv = document.querySelector("#out");
const indiv = document.querySelector("#in");
outdiv.addEventListener('click',function(event){
console.log("out captured");
},{ capture:true });
outdiv.addEventListener('click',function(event){
console.log("out bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
console.log("in bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
console.log("in captured");
},{ capture:true });
</script>
点击in这个div,这个输出结果是:
- out captured
- in captured
- in bubbled
- out bubbled
可以看到,事件捕获(设置capture属性为true)先于事件冒泡(capture默认是false)。事件捕获流程从根元素到后代,而事件冒泡正好相反。
接着稍作变化:
<script>
const outdiv = document.querySelector("#out");
const indiv = document.querySelector("#in");
outdiv.addEventListener('click',function(event){
console.log("out captured");
},{ capture:true });
outdiv.addEventListener('click',function(event){
console.log("out bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
event.stopPropagation(); //添加
console.log("in bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
console.log("in captured");
},{ capture:true });
</script>
再次点击in这个div,输出结果是:
- out captured
- in captured
- in bubbled
可以看到事件冒泡在in这个div处被截断,而事件捕获阶段不变。
我们再做改变:
<script>
const outdiv = document.querySelector("#out");
const indiv = document.querySelector("#in");
outdiv.addEventListener('click',function(event){
event.stopPropagation(); //添加
console.log("out captured");
},{ capture:true });
outdiv.addEventListener('click',function(event){
console.log("out bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
console.log("in bubbled");
},{ capture:false });
indiv.addEventListener('click',function(event){
console.log("in captured");
},{ capture:true });
</script>
再次点击in这个div,
输出结果是:
- out captured
我们会发现事件捕获在out这个div处就被截断,并且同时截断了事件冒泡的整个阶段。
综上,我们可得出结论,event.stopPropagation()既可阻止事件冒泡也可阻止事件捕获。