JS中的DOM事件流(事件冒泡,事件捕获)

JS中的DOM事件流(事件冒泡,事件捕获)

事件流简介

在JS事件循环中,我们接触了很多JS自己触发的事件,但是当我们在网页上进行某些类型的交互时,也会触发事件,比如在某些内容上的点击、鼠标经过某个特定元素或按下键盘上的某些按键。

当一个节点产生一个事件时,该事件会在元素结点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程称为DOM事件流。

DOM事件流最早要从IE和网景公司的浏览器大战说起,IE提出的是冒泡流,而网景提出的是捕获流,后来在W3C组织的统一之下,DOM支持了冒泡流和捕获流,但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流。

DOM事件流原理图

在这里插入图片描述

根据原理图我们可以得出

  • 一个完整的DOM事件流是从window开始,最后回到window的一个过程

  • 事件流被分为三个阶段1-5捕获过程、5-6目标过程、6-10冒泡过程

事件冒泡(由下到上)

  • 意思就是说,假如用户单击了一个元素,该元素拥有一个click事件,那么同样的事件也将会被它的祖先触发,这个事件从该元素开始一直冒泡到DOM树的最上层,这一过程称为事件冒泡

事件捕获(由上到下)

  • 事件捕获和事件冒泡是相反的,也就是说,当用户触发了一个事件的时候,这个事件是从DOM树的最上层开始触发一直到捕获到事件源.

W3C最终做出统一协调

  • 任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达事件源,再从事件源向上进行事件捕获(事件冒泡)。

当今的浏览器对于DOM事件流经过3个阶段:

捕获阶段

  • 当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到触发的目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。事件由页面元素接收,逐级向下,到具体的元素。

目标阶段

  • 当事件不断的传递直到目标节点的时候,最终在目标节点上触发这个事件,就是目标阶段。具体的元素本身。

冒泡阶段

  • 事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。跟捕获相反,具体元素本身,逐级向上,到页面元素(我们平时用的事件绑定就是利用的事件冒泡的原理)。

实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件流</title>
    <script>

    window.onload = function(){
     
     

        var oBtn = document.getElementById('btn');

        oBtn.addEventListener('click',function(){
     
     
            console.log('btn处于事件捕获阶段');
        }, true);
        oBtn.addEventListener('click',function(){
     
     
            console.log('btn处于事件冒泡阶段');
        }, false);

        document.addEventListener('click',function(){
     
     
            console.log('document处于事件捕获阶段');
        }, true);
        document.addEventListener('click',function(){
     
     
            console.log('document处于事件冒泡阶段');
        }, false);

        document.documentElement.addEventListener('click',function(){
     
     
            console.log('html处于事件捕获阶段');
        }, true);
        document.documentElement.addEventListener('click',function(){
     
     
            console.log('html处于事件冒泡阶段');
        }, false);

        document.body.addEventListener('click',function(){
     
     
            console.log('body处于事件捕获阶段');
        }, true);
        document.body.addEventListener('click',function(){
     
     
            console.log('body处于事件冒泡阶段');
        }, false);

    };

    </script>
</head>
<body>
    <a href="javascript:;" id="btn">按钮</a>
</body>
</html>

阻止事件流

  • 如果想只触发当前点击对象的事件,不想让外层的事件触发 ,可以使用不冒泡e.cancelBubble=true或不传播 e.stopPropagation()

实例

    var box = document.querySelector('.box')
    var atr = document.querySelector('.atr')
    box.onclick = function (e) {
    
    
        e.stopPropagation() // 不传播
        console.log('我被点击了box')
    }
    atr.onclick = function (e) {
    
    
        e.cancelBubble=true //不冒泡
        console.log('我被点击了atr')
    }

猜你喜欢

转载自blog.csdn.net/XVJINHUA954/article/details/111715582