阻止事件冒泡和阻止系统默认事件

262 阅读3分钟

事件对象的target属性和currentTarget属性

event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素。

只有被点击的那个目标元素的event.target才会等于event.currentTarget。即event.currentTarget始终是监听事件者就是事件绑定的元素,而event.target是事件的真正发出者就是触发事件执行的元素。

阻止事件冒泡

stopPropagation()方法

阻止事件冒泡就是在触发绑定在目标元素的事件后,中断事件链的传递,不再触发绑定在目标元素的父级元素的与目标元素触发的事件相同类型的事件。

在目标元素触发的事件处理函数中通过事件对象调用stopPropagation方法,event.stopPropagation()可以阻止事件向父级元素冒泡,不在冒泡阶段触发绑定在目标元素的父元素的与目标元素触发的事件相同类型的事件

阻止了后代元素的冒泡不会影响触发事件的目标元素是本身时绑定的事件,因为此时事件链的对象并没有经过其后代元素。

    <style>
        body{
            margin: 0px;
        }
        .box1 {
            width: 400px;
            height: 300px;
            background-color: brown;
            cursor: pointer;
            position: relative;
            left: 100px;
            top: 20px;
        }
        .box2{
            width: 200px;
            height: 200px;
            background-color: red;
            cursor: pointer;
            position: absolute;
            left: 500px;
            top: 20px;
        }
        .box3{
            width: 100px;
            height: 100px;
            background-color: gold;
            cursor: pointer;
            margin: 10px;
            padding: 5px;
            border: 3px solid saddlebrown;
        }
    </style>
    <div class="box1">
        <div class="box2">
             <div class="box3">
                 
             </div>
        </div>
    </div>
    <script>
        let box1=document.querySelector(".box1");
        let box2=document.querySelector(".box2");
        let box3=document.querySelector(".box3");
        box1.addEventListener("click",(e)=>{
            console.log("box1",e.target);
            console.log(e.path,"AOTU")
        });
        box3.addEventListener("click",(e)=>{
            //阻止事件冒泡
            e.stopPropagation();
            console.log("box3",e.target);
            console.log(e.path,"gloria");
        });

image.png

    <script>
        let box1=document.querySelector(".box1");
        let box2=document.querySelector(".box2");
        let box3=document.querySelector(".box3");
        box1.addEventListener("click",(e)=>{
            console.log("box1",e.target);
            console.log(e.path,"AOTU")
        },true);
        box3.addEventListener("click",(e)=>{
            //阻止事件向父级元素的冒泡
            e.stopPropagation();
            console.log("box3",e.target);
            console.log(e.path,"gloria");
        });
    </script>

image.png

设置为父元素的addEventListener第3个参数true时,表示捕获阶段触发绑定的事件,先捕获再目标后冒泡。

ps:addEventListener的第3个参数为true和false都不会阻止事件的传递,true表示捕获阶段触发,false表示冒泡阶段触发。要阻止事件传递的方式就是阻止事件冒泡,需要事件对象调用stopPropagation()方法阻止向父级元素冒泡

事件对象设置属性,event.cancelBubble=true; 低版本的IE浏览器IE8及IE8以下可用这个阻止冒泡。

stopImmediatePropagation()方法

支持stopPropagation的浏览器中也可以用stopImmediatePropagation()方法

事件对象调用stopImmediatePropagation()方法不仅会阻止事件向父级元素的冒泡,也会阻止同一个节点上同一事件的其他的事件处理程序(优先级比它低的就是它后面的同类型事件处理函数不会执行,同元素同事件多处理程序时)即阻止元素同事件类型的其它事件处理函数的触发。stopPropagation()方法只会阻止事件向父级元素冒泡的。

    <script>
        let box1=document.querySelector(".box1");
        let box2=document.querySelector(".box2");
        let box3=document.querySelector(".box3");
        box1.addEventListener("click",(e)=>{
            console.log("box1",e.target);
            console.log(e.path,"AOTU")
        });
        box3.addEventListener("click",(e)=>{
            //阻止事件向父级元素的冒泡
            e.stopPropagation();
            //阻止事件程序传递
            // e.stopImmediatePropagation();
            console.log("box3",e.target);
            console.log(e.path,"gloria");
        });
        box3.addEventListener("click",(e)=>{
            console.log(e.path,"maomao");
        });
    </script>

image.png

目标元素的后面的同类型的事件其事件处理函数也运行了

    <script>
        let box1=document.querySelector(".box1");
        let box2=document.querySelector(".box2");
        let box3=document.querySelector(".box3");
        box1.addEventListener("click",(e)=>{
            console.log("box1",e.target);
            console.log(e.path,"AOTU")
        });
        box3.addEventListener("click",(e)=>{
            //阻止事件向父级元素的冒泡
            // e.stopPropagation();
            //阻止事件程序传递
            e.stopImmediatePropagation();
            console.log("box3",e.target);
            console.log(e.path,"gloria");
        });
        box3.addEventListener("click",(e)=>{
            console.log(e.path,"maomao");
        });
    </script>

image.png

目标元素的后面的同类型的事件其事件处理函数并没有运行

易错点:阻止事件冒泡以及设计让监听器在捕获阶段运行等都是指的同一个事件类型,不同类型的事件会有不同的几条事件链,事件链是独立的。

    <script>
        let box1=document.querySelector(".box1");
        let box2=document.querySelector(".box2");
        let box3=document.querySelector(".box3");
        box1.addEventListener("mousedown",(e)=>{
            console.log("box1",e.target);
            console.log(e.path,"AOTU")
        });
        box3.addEventListener("click",(e)=>{
            //阻止事件向父级元素的冒泡
            // e.stopPropagation();
            //阻止事件程序传递
            e.stopImmediatePropagation();
            console.log("box3",e.target);
            console.log(e.path,"gloria");
        });
        box3.addEventListener("mousedown",(e)=>{
            console.log(e.path,"maomao");
        });
    </script>

image.png

不同类型的事件并没有阻止,mousedown是按下就触发,click要按下松开后才会触发。

阻止系统默认事件

默认事件:表单一点击提交按钮(submit)跳转页面、点击a标签默认页面跳转,右键菜单等等

    <a href="https://www.baidu.com/">默认跳转连接</a>
    <script>
        let a=document.querySelector("a");
        a.addEventListener("click",(event)=>{
            console.log(event);
        });
    </script>

元素有系统默认事件,再给元素绑定同类型的事件,会先触发绑定的事件,再触发系统默认的事件。属性绑定和行内绑定的同类事件也不会覆盖系统默认的事件。

2.gif

事件对象调用方法preventDefault()可阻止系统默认事件的触发,event.preventDefault();

低版本IE9以下事件对象修改returnValue属性,event.returnValue=false;

    <a href="https://www.baidu.com/">默认跳转连接</a>
    <script>
        let a=document.querySelector("a");
        a.addEventListener("click",(event)=>{
            event.preventDefault();
            console.log(event);
        });
    </script>

用return false; 以元素属性绑定的方式注册的事件才生效,用给事件添加监听器addEventListener/attachEvent绑定的事件是不生效的