• 事件冒泡和事件捕获


    JS事件流原理图:

    1005354-20161222125521823-1914047378[1]

    由此可知道,一个完整的JS事件流是从window开始,最后回到window的一个过程;事件流被分为三个阶段:捕获过程(1~5)、目标过程(5~6)、冒泡过程(6~10);

    事实上,捕获过程和冒泡过程是完全相反的过程,即事件由父元素向子元素传播和子元素向父元素传播的过程。

    事件捕获

    事件捕获在事件绑定的第二种形式下才能实现,事件绑定的第二种形式

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>事件捕获</title>
        <style>
            div{padding:40px;}
            #div1{
                background: red;
            }
            #div2{
                background:green;
            }
            #div3{background: blue;}
        </style>
        <script>
            window.onload=function(){
                var oDiv1=document.getElementById('div1');
                var oDiv2=document.getElementById('div2');
                var oDiv3=document.getElementById('div3');
    
                function fn1(){
                    alert(this.id);
                }
                //点击div3部分时,分别弹出div1,div2,div3
                oDiv1.addEventListener('click',fn1,true);//为true时,是事件捕获   false=冒泡
                oDiv2.addEventListener('click',fn1,true);
                oDiv3.addEventListener('click',fn1,true);
            }
        </script>
    </head>
    <body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    </body>
    </html>

    上面例子中,点击div3时,div1会接收到两个点击事件,一个是在捕获阶段触发了div1的点击事件,一个是在冒泡阶段触发了div1的点击事件;addEventListener中的第三个参数:true----捕获,false-----冒泡;上面设置为true即捕获阶段的点击事件被触发了

    注:div1会接收到两个点击事件与是否触发该事件无关

    再来个例子:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>事件捕获</title>
        <style>
            div{padding:40px;}
            #div1{
                background: red;
            }
            #div2{
                background:green;
            }
            #div3{background: blue;}
        </style>
        <script>
            window.onload=function(){
                var oDiv1=document.getElementById('div1');
                var oDiv2=document.getElementById('div2');
                var oDiv3=document.getElementById('div3');
    
                        
                oDiv1.addEventListener('click',function(){
                    alert(1);
                },false);
                oDiv1.addEventListener('click',function(){
                    alert(3);
                },true);
                oDiv3.addEventListener('click',function(){
                    alert(2);
                },false);
                //点击div3,分别弹出3,2,1
            }
        </script>
    </head>
    <body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    </body>
    </html>

    点击div3,查看弹出的结果分别是:3、2、1

    点击div3时,div1会接收到两个点击事件,在捕获阶段(true),触发了div1的点击事件,弹出结果:3;在冒泡阶段,触发了div3的点击事件,弹出结果:2,然后触发了div1的点击事件,弹出结果:1

    事件冒泡

    当一个元素接受到事件的时候,会把它接收到的所有事件传播给它的父级,一直到顶层window,叫事件冒泡机制;

    例子:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>事件冒泡</title>
        <style>
            div{padding:40px;}
           #div1{
               background: red;
           }
           #div2{
               background:green;
           }
            #div3{background: blue;}
        </style>
        <script>
            window.onload=function(){
                var oDiv1=document.getElementById('div1');
                var oDiv2=document.getElementById('div2');
                var oDiv3=document.getElementById('div3');
    
                function fn1(){
                    alert(this.id);
                }
    
                //事件函数绑定
                oDiv1.onclick=fn1;//告诉div1,如果它接收到了一个点击事件,那它就去执行fn1
                oDiv2.onclick=fn1;
                oDiv3.onclick=fn1;//div3,div1 事件冒泡
            }
        </script>
    </head>
    <body>
    <div id="div1">
        <div id="div2">
            <div id="div3"></div>
        </div>
    </div>
    </body>
    </html>

    阻止冒泡:在当前要阻止冒泡的事件函数中调用event.cancelBubble=true;

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>阻止冒泡</title>
        <style>
            #div1{
                width:100px;
                height:200px;
                border:1px solid red;
                display: none;
            }
        </style>
        <script>
            window.onload=function(){
                var oBtn=document.getElementById('btn1');
                var oDiv=document.getElementById('div1');
    
                oBtn.onclick=function(ev){
                    var oEvent=ev||event;
                    //阻止当前事件函数事件冒泡
                    oEvent.cancelBubble=true;
                    oDiv.style.display='block';
                }
                document.onclick=function(){
                   /* setTimeout(function(){//观察事件冒泡:div出现一秒钟后隐藏了
                        oDiv.style.display='none';
                    },1000);*/
                    oDiv.style.display='none';
                }
            }
        </script>
    </head>
    <body>
    <input type="button" value="按钮" id="btn1">
    <div id="div1">点击按钮div就出现,点击除按钮以外的部分div就消失</div>
    </body>
    </html>

    对比没有取消冒泡事件时的效果,下面用了延时器一遍观察效果

    事件冒泡的运用

    下面是一个网站中常见的功能——分享到

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>事件冒泡</title>
        <style>
            #div1{
                width:100px;
                height:200px;
                background: red;
                position: absolute;
                left:-100px;
                top:100px;
            }
            #div2{
                width:30px;
                height:60px;
                position: absolute;
                right:-30px;
                top:70px;
                background:#000000;
                color:#ffffff;
                text-align: center;
            }
        </style>
        <script>
            window.onload=function(){
                var oDiv=document.getElementById('div1');
                oDiv.onmouseover=function(){
                    this.style.left=0+'px';//鼠标移动到div2时,div2接收到over、out事件时它自己不做,传播给父级div1执行
                }
                oDiv.onmouseout=function(){
                    this.style.left=-100+'px';
                }
            }
        </script>
    </head>
    <body>
    <div id="div1">
        <div id="div2">分享到</div>
    </div>
    </body>
    </html>

    效果:

  • 相关阅读:
    SQL Server 备份方案
    Azure 学习笔记
    SEO – 大杂烩
    Asp.net core 学习笔记之 Tag Helper
    读取注册表
    DOM学习历程-3
    inno setup给控制的那边加图标
    C++生成exe安装到别人那边无法使用缺少dll
    inno setup 最后
    inno setup
  • 原文地址:https://www.cnblogs.com/jnslove/p/6942105.html
Copyright © 2020-2023  润新知