js基础_01_事件冒泡与捕获

131 阅读2分钟

事件冒泡 与 事件捕获

前端工作开发中一定会遇到事件冒泡的时候,比如我想点击元素内部的button,但是外部元素上面同时也绑定着chick事件,这种时候就会遇到事件冒泡现象。 如下面的例子:

   <body>
    <div  class="outer">
        <div class="middle">
            <div class="inner">
                <button onclick="console.log(this)">click me</button> <!-- 点击这里  -->
            </div>
        </div>
    </div>
</body>
 <script type="module">
     //分别给每一层的元素都添加点击事件
     const $ = (selector) => document.querySelector(selector)
     console.log($)
     $('.outer').addEventListener("click",e=>{
         console.log(`%c outer ${e}`,'color:orange')
     },false)
     $('.middle').addEventListener("click",e=>{
         console.log(`%c middle ${e}`,'color:palegreen')
     },false)
     $('.inner').addEventListener("click",e=>{
         console.log(`%c inner ${e}`,'color:pink')
     },false)
 </script>

控制台输出

image.png

从控制台输出可以看出我们点击了botton,从内而外 依次出发了inner、middle、outer上的click事件,,这种现象就是事件冒泡。

事件捕获与事件冒泡的现象正好相反,是由外而内的触发

    <body>
    <div  class="outer">
        <div class="middle">
            <div class="inner">
                <button onclick="console.log(this)">click me</button> <!-- 点击这里  -->
            </div>
        </div>
    </div>
</body>
 <script type="module">
     const $ = (selector) => document.querySelector(selector)
     console.log($)
     $('.outer').addEventListener("click",e=>{
         console.log(`%c outer ${e}`,'color:orange')
     },true)
     $('.middle').addEventListener("click",e=>{
         console.log(`%c middle ${e}`,'color:palegreen')
     },true)
     $('.inner').addEventListener("click",e=>{
         console.log(`%c inner ${e}`,'color:pink')
     },true)
 </script>

控制台输出

image.png 上面两种写法的区别在于addEventLinstener的第三个参数不一样,true的时候是事件捕获,false 的时候是事件冒泡。

这里面我们打印了参数e

我们可能会分不清e.target 和 e.currentTarget 的情况,我们看下面的代码可能回给你带来启示:

    <body>
    <div  class="outer">
        <div class="middle">
            <div class="inner">
                <button onclick="console.log(this)">click me</button>
            </div>
        </div>
    </div>
</body>
 <script type="module">
     const $ = (selector) => document.querySelector(selector)
     console.log($)
     $('.outer').addEventListener("click",e=>{
         console.log(`%c e.target`,'color:orange',e.target)
         console.log(`%c e.currentTarget`,'color:orange', e.currentTarget)
        //  console.log(`%c outer ${e}`,'color:orange')
     },false)
     $('.middle').addEventListener("click",e=>{
        // console.log(`%c e.target`,'color:palegreen',e.target)
        //  console.log(`%c e.currentTarget`,'color:palegreen',e.currentTarget)
        //  console.log(`%c middle ${e}`,'color:palegreen')
     },false)
     $('.inner').addEventListener("click",e=>{
        // console.log(`%c e.target`,'color:pink',e.target)
        //  console.log(`%c e.currentTarget`,'color:pink',e.currentTarget)
        //  console.log(`%c inner ${e}`,'color:pink')
     },false)

 </script>

当我们分别点击outer、middle和inner 的时候打印如下

image.png

我们可以发现currentTarget始终都是一个,而target随着我们的点击而改变

这里我们就可以了解到了,e.target实时点击的那个对象,而currentTarget是我们绑定addEventListener的当前对象。

聊到事件冒泡就不得不提如何阻止事件冒泡。

阻止事件冒泡

大多数时候我们是不希望事件向上冒泡的,我们应该如何阻止这种行为呢?

    <body>
    <div  class="outer">
        <div class="middle">
            <div class="inner">
                <button onclick="console.log(this)">click me</button>
            </div>
        </div>
    </div>
</body>
 <script type="module">
     const $ = (selector) => document.querySelector(selector)
     console.log($)
     $('.outer').addEventListener("click",e=>{
        //  console.log(`%c e.target`,'color:orange',e.target)
        //  console.log(`%c e.currentTarget`,'color:orange', e.currentTarget)
        e.stopPropagation()
         console.log(`%c outer ${e}`,'color:orange')
     },false)
     $('.middle').addEventListener("click",e=>{
        // console.log(`%c e.target`,'color:palegreen',e.target)
        //  console.log(`%c e.currentTarget`,'color:palegreen',e.currentTarget)
        e.stopPropagation()
         console.log(`%c middle ${e}`,'color:palegreen')
     },false)
     $('.inner').addEventListener("click",e=>{
        // console.log(`%c e.target`,'color:pink',e.target)
        //  console.log(`%c e.currentTarget`,'color:pink',e.currentTarget)
         e.stopPropagation()
         console.log(`%c inner ${e}`,'color:pink')
     },false)

 </script>

可以看到我们这里用到了e.stopPropagation(),我们再来点击,就会发现冒泡事件被阻止了。

在vue中我们也经常会遇到这个问题,通常我们是怎么解决的呢?

vue提供可绑定事件的语法糖例如:@click,还提供了修饰符.stop 用来阻止事件传递的,所以我们像下面这样写就可以了

    <div @click.stop='clickEvent'></div>

好了,以上就是对事件冒泡的总结和理解。