事件捕获与事件冒泡

事件捕获与事件冒泡

1.事件

指用户或浏览器做的某个动作,能被JavaScript检测到的行为。比如:我们点击了网页上的某个按钮,就是一个click事件。而DOM 允许 JavaScript 对 HTML事件作出反应:如弹出一个对话框,跳转页面等。 不妨把事件想象成一个信号:我们按下了一个按钮,产生了一个信号,这个信号触发网页弹出了一个对话框。

2.事件流

这个信号是可以传递的。如下我们定义三个嵌套的div标签,从内向外依次是granson、son、father。我们给三个标签都注册事件,让它们在对话框显示自己的类名。当我们单击白色grandson盒子时,在弹出grandson的对话框后,会发现son和father也会依次弹出对话框,但是我们并没有点击它俩。这是因为click事件传递了,从grandson传递到了son、father中,即事件流。

在这里插入图片描述

	<div class="father">father
        <div class="son">son
            <div class="grandson">grandson</div>
        </div>
    </div>
    <script>
        var father=document.querySelector('.father');
        father.addEventListener('click',function(){
        alert('father');
        },false)
        var son=document.querySelector('.son');
        son.addEventListener('click',function(){
            alert('son');
        },false)
        var grandson=document.querySelector('.grandson');
        grandson.addEventListener('click',function(){
            alert('grandson');
        },false)
    </script>

单我们点击天蓝色father盒子时,只会弹出了father的对话框,click事件并没有传递回son和grandson。
为什么只能向外传没有向里传,事件的传递方向应该如何?对此,微软公司和网景公司给出了不同的概念
事件冒泡:微软公司提出事件触发顺序是从特定的事件目标到最不特定的事件目标。
即从事件触发的节点向它的父节点传递,直到DOM最顶层。顺序为:
1、 div
2、 body
3、 html
4、document
在上面的例子中,如果我们单击黄色son盒子,会发现只弹出son和father。因为事件只向父级节点传递,而grandson是son的子节点。如果我们添加了body、html、document的事件,那它们也会被依次触发。
与之相反,网景公司提出了
事件捕获:事件的传播是从最不特定的事件目标到最特定的事件目标。即从它的父节点向事件触发的节点传递。顺序为:
1、document
2、 html
3、 body
4、 div
当addEventListener()事件监听方法中的第三个参数为true时,事件句柄在捕获阶段执行,当该参数为false(默认)时,事件句柄在冒泡阶段执行。
我们将addEventListener()事件监听的第三个参数改为true,则上面的代码由冒泡触发改为了捕获触发,单我们点击黄色son盒子时,会依次弹出father、son的对话框。同样如果我们添加了body、html、document的事件,那触发顺序会变为document、html、body、father、son。

DOM事件流

在这里插入图片描述

3.事件流的应用-事件委托

利用事件流的特性,我们可以简化代码,减少对DOM的操作,提升代码性能。如当有多个子节点需要设置相同的事件监听器,如果单独为每个子节点设置事件监听器,代码会十分臃肿,我们可以设置在其父节点上,只需要设置一次事件监听器。由冒泡原理,当任何一个子节点收到事件信号,由其父节点代替执行事件执行函数,即事件委托。
如下设置一个ul标签,并在里面放置5个子元素li,我们单击任何一个li时,让网页弹出窗口,我们只需把事件监听器设置在ul上即可。
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var uls=document.querySelector('ul');
        uls.addEventListener('click',function (e) {
            alert('Hello Bug。');
        })
    </script>

4. 阻止事件冒泡/捕获

可以使用stopPropagation()方法阻止事件在事件冒泡、事件捕获、事件处理阶段的进一步传播。
如想将案例中的事件冒泡阻止在son节点,在son的事件监听器下写入stopPropagation()方法即可,在弹出grandson和son的提示框后将阻止事件冒泡,不再往上传递。
完整代码:
<!DOCTYPE html>
<html lang="zh-CN">
<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>eventBubbling</title>
    <style>
        .father{
            position: relative;
            background-color: skyblue;
            width: 600px;
            height: 600px;
            margin:100px auto;
            font-size: 25px;
            text-align: center;   
        }
        .son{
            position: absolute;
            background-color:yellow;
            width:400px;
            height: 400px;
            left:50%;
            top:50%;
            margin-left: -200px;
            margin-top: -200px;
            text-align: center;
                font-size: 25px;
            }
            .grandson{
                position:absolute;
                background-color: white;
                width:200px;
                height: 200px;
                left:50%;
                top:50%;
                margin-top: -100px;
                margin-left: -100px;
                text-align: center;
                font-size: 25px;
            }
     </style>         
</head>
<body>
    <div class="father">father
        <div class="son">son
            <div class="grandson">grandson</div>
        </div>
    </div>
    <script type='text/javascript'>
        var father=document.querySelector('.father');
        father.addEventListener('click',function(){
        alert('father');
        },false)
        var son=document.querySelector('.son');
        son.addEventListener('click',function(e){
            alert('son');
            e.stopPropagation();    //阻止事件冒泡
        },false)
        var grandson=document.querySelector('.grandson');
        grandson.addEventListener('click',function(){
            alert('grandson');
        },false)
    </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值