关于事件冒泡和事件代理,看这一篇就够了!(上篇)

Hello,最近又准备面试了,通过前几次面试经历,有很深刻的感受,一定要注重基础,注重基础,注重基础!
不要觉得自己用了一些轮子写了一些看起来很不错的项目和功能,就一定能找到好工作。那些轮子不是你写的,你只是一个搬运工…
我们要养成一个好的习惯,不要觉得我用这个轮子写了这个功能,这个功能就是我实现的,我就很厉害,厉害的是轮子,和你没关系,你做的事情,几乎所有人都能做。


最近复习到了原生JS的部分,这期给大家带来事件冒泡事件代理。这部分的内容面试也经常遇到,在大厂面试中出现的频率也很频繁。

事件冒泡的来龙去脉

啥是事件冒泡呢,我们以一个简单的例子了解一下。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .father {
            width: 200px;
            height: 200px;
            border: 1px solid #000;
        }
        .child {
            width: 100px;
            height: 100px;
        }
        .child.child-1 {
            background-color: red;
        }
        .child.child-2 {
            background-color: orange ;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="child child-1"></div>
        <div class="child child-2"></div>
    </div>
    <script>
        var oFather = document.getElementsByClassName('father')[0],
            oChild1 = document.getElementsByClassName('child-1')[0],
            oChild2 = document.getElementsByClassName('child-2')[0];
        oFather.onclick = function() {
            console.log('father');
        }
        oChild1.onclick = function() {
            console.log('child-1');
        }
        oChild2.onclick = function() {
            console.log('child-2');
        }

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

上面的代码,我写了一个divfather,内容有两个同级div,分别为child-1child-2
并且我分别给它们添加了样式。
在浏览器中,它的渲染结果如下:
在这里插入图片描述

然后我写了一些JS代码,通过DOM操作,分别拿到三个div的节点,然后分别绑定各自点击事件的处理函数。

那么我现在点击一下网页中的红色区域,应该输出什么呢?
正常的思路应该觉得肯定输入child-1呀,因为红色的区域代表divclass属性为child child-1的部分。

那么我们看一下实际的效果。
在这里插入图片描述
控制台先输出了child-1,然后输出了father

这是什么原因呢?

肯定有同学会说,因为child-1father的内部,你点击了child-1也相当于点击了father

ok,思路很清晰,那么我稍微改一下CSS代码。

在这里插入图片描述
现在child-1child-2在视图上脱离了father容器,我继续点击红色区域会输出什么?
在这里插入图片描述
还是相同的结果。

又有同学要说了,虽然你在视图上让child-1child-2脱离了father,但是在实际的HTML结构中,child-1child-2仍然属于father的子标签。

ok,没有问题,这种思路完全没有问题,但是这样的思路不利于我们学习事件冒泡的原理。

我们换一个思路思考一下。
我在body上添加一个点击事件的处理函数,并且进行输出呢。我们再次点击child-1的时候,会不会触发body标签的输出?

在这里插入图片描述
在这里插入图片描述
没错,body的点击事件也会被触发。

我们按照这个思路,继续向上寻找,给html标签也绑定,给document也绑定,最后给window也绑定上点击事件的处理函数。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
果然,这个点击事件的处理函数,被逐级触发~~~~
是不是很奇妙,虽然按照之前的思路,也可以解释的过去,但是还是希望大家以事件冒泡的思路去理解这个问题。

其实在很多的业务开发中,都会碰到类似的问题,我只是想让它自己的点击事件触发,但是它父类的点击事件也会跟着不小心触发,这就是烦恼。

那么我们介绍完事件冒泡的来龙去脉之后,我们要如何避免它呢?

避免事件冒泡的产生

在这里插入图片描述
我们在oChild1的点击事件处理函数中,添加一个参数e,并且在函数内部,输出这个e。然后看下控制台。
在这里插入图片描述
有一个MouseEvent的对象被打印出来。
我们试着跟踪一下它的原型链。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到,跟着它的原型链走,分别经历了MouseEvent -> mouseEvent -> UIEvent -> Event -> Object

我们着重看一下,在Event对象中,有一个stopPropagation方法,这个就是停止事件冒泡的方法,然后cancelBubble属性,默认是false
在这里插入图片描述
这两个都可以停止事件冒泡。

它们的区别主要是stopPropagation()是符合W3C标准的,也就是说,大部分的浏览器都可以使用,cancelBubbleIE浏览器中处理事件冒泡的属性。

所以,在处理浏览器兼容的时候,它们才会有区别,功能是一摸一样的。

oChild1.onclick = function(e) {
    console.log(e);
    var e = e || window.event;
    if (e.stopPropagation) {
        e.stopPropagation();
    }else {
        e.cancelBubble = true;
    }
    console.log('child-1');
}

这样写,就是最标准的,考虑兼容的,处理事件冒泡的方法。

在这里插入图片描述
经过我们的处理,现在再次点击红色区域的时候,它只会输出点击事件处理函数中的输出语句,不会向上冒泡。

ok,以上就是关于事件冒泡的来龙去脉以及处理方法。

因为文章篇幅有限,关于事件代理的内容,下期再介绍~~~

顺便说一下,最近在找实习,有合适工作的可以给我内推一下~~,前端岗,最好base北京

联系方式
QQ:505417246
微信:18331092918

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CreatorRay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值