event.stopPropagation() 阻止捕获和冒泡阶段中当前事件的进一步传播。

在这之前先说一下事件触发的原理

 事件触发原理

 事件触发整体有三个阶段构成:捕获阶段 -> 目标阶段(不显示) -> 冒泡阶段(默认)

        捕获阶段是由外向内

        冒泡阶段是由内向外

捕获阶段    目标阶段    冒泡阶段

            外                    内

             |                        |

            内                    外

接下来用4个嵌套的div举例说明

    <div class="div1">div1
        <div class="div2">div2
            <div class="div3">div3
                <div class="div4">div4</div>
            </div>
        </div>
    </div>

 具体css代码不做展示,效果图如下:

 

JavaScript代码如下:



        var div1=document.querySelector(".div1");
        var div2=document.querySelector(".div2");
        var div3=document.querySelector(".div3");
        var div4=document.querySelector(".div4");

        div1.addEventListener("click",clickhandler1);
        div2.addEventListener("click",clickhandler2);
        div3.addEventListener("click",clickhandler3);
        div4.addEventListener("click",clickhandler4);
        
        function clickhandler1(e){
            console.log("div1")
        }
        function clickhandler2(e){
            console.log("div2")
          
        }
        function clickhandler3(e){
            console.log("div3)
    
        }
        function clickhandler4(e){
            console.log("div4)
           
        }

 event.stopPropagation() 阻止捕获和冒泡阶段中当前事件的进一步传播

        说白了就是当侦听的事件是捕获时,阻断的就是捕获过程,当侦听的事件是冒泡时,阻断的就是冒泡过程

1. 接下来看第一个例子,当设置div3是冒泡时,也就是默认值false

        div1.addEventListener("click",clickhandler1);
        div2.addEventListener("click",clickhandler2);
        div3.addEventListener("click",clickhandler3,false);
        div4.addEventListener("click",clickhandler4);

那当阻断div3时,点击div4时

        function clickhandler1(e){
            console.log("div1")
        }
        function clickhandler2(e){
            console.log("div2")
          
        }
        function clickhandler3(e){
            console.log("div3")
            e.stopPropagation(); //阻止冒泡事件进一步传播
        }
        function clickhandler4(e){
            console.log("div4")
            
        }

那输出的结果就是

因为,所有的div都设置侦听的是冒泡阶段,所以捕获阶段不触发,冒泡输出结果从内往外输出,应该是div4->div3->div2->div1

但是在div3用了e.stopPropagation()阻止了冒泡进一步传播,所以只输出了div4->div3

2、当设置四个div都是侦听捕获阶段时,当阻断div3时,点击div4时

        div1.addEventListener("click",clickhandler1,true);
        div2.addEventListener("click",clickhandler2,true);
        div3.addEventListener("click",clickhandler3,true);
        div4.addEventListener("click",clickhandler4,true);
        
        function clickhandler1(e){
            console.log("div1")
        }
        function clickhandler2(e){
            console.log("div2")
          
        }
        function clickhandler3(e){
            console.log("div3")
            e.stopPropagation(); 
        }
        function clickhandler4(e){
            console.log("div4")
            // e.stopPropagation(); 
        }

 输出结果应是

 因为侦听的四个div都是捕获阶段,所以应该由外向内,输出的是div1 -> div2 -> div3 ->div4

但是div3用e.stopPropagation()阻止了捕获的进一步传播,所以只输出div1 -> div2 -> div3

3、第三个例子,设置div1,div3侦听的是冒泡阶段,div2,div4侦听的是捕获阶段,那么当设置阻断div3时

        div1.addEventListener("click",clickhandler1);
        div2.addEventListener("click",clickhandler2,true);
        div3.addEventListener("click",clickhandler3);
        div4.addEventListener("click",clickhandler4,true);
        
        function clickhandler1(e){
            console.log("div1")
        }
        function clickhandler2(e){
            console.log("div2")
          
        }
        function clickhandler3(e){
            console.log("div3")
            e.stopPropagation(); 
        }
        function clickhandler4(e){
            console.log("div4")
            
        }

这个时候四个div有捕获阶段,也有冒泡阶段,优先捕获阶段,也就是先输出捕获阶段div2、div4,后输出冒泡阶段div3、div1

注意,捕获阶段由外向内,所以输出的是div2 -> div4

冒泡阶段由内向外,所以输出的是div3 -> div1

 

所以最后输出应该是div2 -> div4 -> div3 -> div1

但是div3用e.stopPropagation()阻止了冒泡的进一步传播,所以输出结果应该是div2 -> div4 -> div3

 

那么同理 如果设置div1,div3侦听的是捕获阶段,div2,div4侦听的是冒泡阶段,那么当设置阻断div3时

        div1.addEventListener("click",clickhandler1,true);
        div2.addEventListener("click",clickhandler2);
        div3.addEventListener("click",clickhandler3,true);
        div4.addEventListener("click",clickhandler4);
        
        function clickhandler1(e){
            console.log("div1")
        }
        function clickhandler2(e){
            console.log("div2")
          
        }
        function clickhandler3(e){
            console.log("div3")
            e.stopPropagation(); 
        }
        function clickhandler4(e){
            console.log("div4")
            
        }

这个时候同样四个div有捕获阶段,也有冒泡阶段,优先捕获阶段,也就是先输出捕获阶段div1、div3,后输出冒泡阶段div4、div2

再次注意,捕获阶段由外向内,所以输出的是div1 -> div3

冒泡阶段由内向外,所以输出的是div4 -> div2

所以最后输出应该是div1 -> div3 -> div4 -> div2

但是div3用e.stopPropagation()阻止了捕获的进一步传播,所以输出结果应该是div1 -> div3


 简单总结一些注意点:

因为上边的例子都是点击最里层的元素div4,所以根据事件的触发原理:捕获阶段 -> 目标阶段(不显示) -> 冒泡阶段(默认)

点击的是div4,所以目标阶段就是div4,捕获阶段就是有外向内,div1 -> div2 -> div3 -> div4

冒泡阶段是由内向外div4 -> div3 -> div2 -> div1,

所以整个点击div4事件的原理就是:

捕获阶段由外向内(div1 -> div2 -> div3 -> div4) -> 目标div4  ->  冒泡阶段由内向外(div4 -> div3 -> div2 -> div1)

设置在哪个阶段 侦听,就获取哪个阶段的元素或方法,侦听捕获阶段1,3,就获取div1,div3

侦听冒泡阶段2,4,就获取div4,div2

千万注意捕获阶段和冒泡阶段的顺序!

e.stopPropagation() 就是阻止之后的冒泡或者捕获继续传播,说白了就是截断,不再侦听


后续有什么不懂可以私聊我,或者评论

最后大家可以试着想一下,当点div1,div2,div3时输出div1,点div4时,输出div4。这样该怎么实现?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐