欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

浅谈js事件冒泡和事件捕获

程序员文章站 2022-06-28 10:47:12
前言:最近正好在找工作,当面试官问到我事件冒泡和事件捕获的时候,我想我的回答并不全面合理,基于这方面的原因,我打算抽点时间来和大伙聊聊, 并不一定全面,多多包涵。 首先咱们先聊聊事件冒泡: 什么是事件冒泡 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发 元素->父元 ......

前言:最近正好在找工作,当面试官问到我事件冒泡和事件捕获的时候,我想我的回答并不全面合理,基于这方面的原因,我打算抽点时间来和大伙聊聊,

           并不一定全面,多多包涵。

 

首先咱们先聊聊事件冒泡:

什么是事件冒泡

  • 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发
  • 元素->父元素->body->html->document->window
  • 事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
<!doctype html>
<html>
<head lang="en">
    <meta charset="utf-8">
    <title></title>
    <style>
        #box{
            width: 300px;
            height: 300px;
            background-color: hotpink;
            position: relative;
        }

        #son{
            width: 100px;
            height: 100px;
            position: absolute;

            left: 350px;
            top: 350px;

            background-color: yellowgreen;
        }
    </style>
</head>
<body>

<div id="box">
    <input type="button" value="点我" id="btn"/>

    <div id="son"></div>
</div>

</body>
</html>

<script>

    window.onclick = function () {

        alert("window被点击了");
    }

    document.onclick = function () {

        alert("文档被点击了");
    }

    document.documentelement.onclick = function () {

        alert("html被点击了");
    }

    document.body.onclick = function () {

        alert("body被点击了");
    }

    document.getelementbyid("box").onclick = function () {

        alert("我是骚粉的大盒子");
    };

    document.getelementbyid("btn").onclick = function () {

        alert("我是小按钮");
    };

    document.getelementbyid("son").onclick = function () {

        alert("我是又黄又绿的小盒子");
    };
</script>

 

事件冒泡的好处

  • 事件冒泡好处:如果想给父元素的多个子元素添加事件,我们可以只需要给父元素添加事件即可,然后
  • 通过获取事件源(e.target)就可以得知是哪一个子元素触发了这个事件
<!doctype html>
<html>
<head lang="en">
    <meta charset="utf-8">
    <title></title>
</head>
<body>

<ul id="ul1">
    <li>隔壁老王1</li>
    <li>隔壁老王2</li>
    <li>隔壁老王3</li>
    <li>隔壁老王4</li>
    <li>隔壁老王5</li>
</ul>

</body>
</html>

<script>

    var ul = document.getelementbyid("ul1");

    //1.如果想给ul中的每一个li标签添加点击事件,以前的做法需要遍历ul的li标签逐个添加
    //    for (var i = 0; i < ul.children.length; i++) {
    //
    //        ul.children[i].onclick = function () {
    //
    //            alert(this.innerhtml);
    //        }
    //    }

    //2.使用时间冒泡:只需要给父元素添加点击事件即可
    ul.onclick = function (e) {

        e = e || window.event;

        var target = e.target || e.srcelement;

        console.log(target.innerhtml);

        //target:事件源:触发本次事件的源头
        alert(e.target.innerhtml);
    }

</script>

事件冒泡的影响

  • 事件冒泡会导致需求冲突:例如我想要添加一个功能,弹出登录窗之后点击body空白区域让登陆窗消失
  • 此时a标签弹出登录窗的点击事件会触发body的点击事件,导致登陆窗一出来就消失

阻止事件冒泡

  • 阻止事件冒泡:让同名事件不要在父元素中冒泡(触发)
     * 说人话:点击一个元素只会触发当前元素的事件,不会触发父元素的同名事件
    
  • 语法: 事件对象.stoppropagation() ie8及之前不支持
  • 事件对象.cancelbubble = true ie8之前支持
  • 注意:如果想要阻止事件冒泡,一定要在触发事件的函数中接收事件对象

 

事件捕获

  • 1.事件冒泡:从触发事件元素,一级一级往上找父元素触发同名事件,如果有就触发
  • 2.事件捕获:从最*的父元素一级一级往下找子元素触发同名事件,直到触发事件的元素为止
    • 事件捕获与事件冒泡触发事件的顺序完全相反
  • 3.事件捕获,只能通过addeventlistener并且参数写true才是事件捕获
    • 其他都是冒泡(不是通过addeventlistener添加、addeventlistener参数为false)
  • 4.事件对象.stoppropagation() 除了可以阻止冒泡还可以阻止捕获
  • 5.ie8及以前没有捕获!
<!doctype html>
<html>
<head lang="en">
    <meta charset="utf-8">
    <title></title>
    <style>
        #box {
            width: 300px;
            height: 300px;
            background-color: hotpink;
            position: relative;
        }

        #son {
            width: 100px;
            height: 100px;
            position: absolute;

            left: 350px;
            top: 350px;

            background-color: yellowgreen;
        }
    </style>
</head>
<body>

<div id="box">

    <div id="son"></div>
</div>


</body>
</html>

<script>

var box = document.getelementbyid("box"); var son = document.getelementbyid("son"); window.addeventlistener("click", function () { alert("这是window"); },true) document.addeventlistener("click", function () { alert("这是document"); },true) document.documentelement.addeventlistener("click", function (e) { e = e || window.event; alert("这是html"); e.stoppropagation();//阻止事件冒泡和事件捕获 },true) document.body.addeventlistener("click", function () { alert("这是body"); },true) //参数3:默认是false,代表是支持事件冒泡 box.addeventlistener("click", function () { alert("这是box"); },true) son.addeventlistener("click", function () { alert("这是son"); },true) </script>

事件的三个阶段

  • 1.事件一共有三个阶段:事件的执行顺序
    • 1--捕获阶段 :
    • 2--目标阶段 :
    • 3--冒泡阶段 :
  • 2.事件对象.eventphase 可以获得触发这个事件时,到底是哪个阶段
  • 3.先从最*往下一级一级捕获,然后到目标的捕获,目标的冒泡,再一级一级往上冒泡
<!doctype html>
<html>
<head lang="en">
    <meta charset="utf-8">
    <title>标题</title>
    <style>
        .one {
            width: 200px;
            height: 200px;
            background-color: pink;
        }
        .son {
            width: 100px;
            height: 100px;
            background-color: green;
            position: absolute;
            left: 250px;
            top: 250px;
        }
    </style>
</head>
<body>
<div class="one" id="box">
    <input type="button" value="按钮" id="btn"/>
    <div class="son" id="son"></div>
</div>

<script>
   
    var box = document.getelementbyid("box");
    var btn = document.getelementbyid("btn");
    var son = document.getelementbyid("son");

    document.addeventlistener("click",function (e) {
        alert("document"+ e.eventphase);
    },true) ;//true表示事件捕获,所以是阶段1,并且优先执行

    document.body.addeventlistener("click", function (e) {
        alert("哈哈,我是body"+ e.eventphase);
    },false);


    box.addeventlistener("click",function (e) {
        alert("哈哈哈,我是粉色的盒子box..."+ e.eventphase);
    },false);



    btn.addeventlistener("click",function (e) {
        alert("哈哈哈,我是按钮btn..."+ e.eventphase);
    },false);



    son.addeventlistener("click",function (e) {
        alert("嘻嘻嘻,我是绿色的盒子son"+ e.eventphase);

    },false);

</script>
</body>
</html>