JS的事件冒泡和事件捕获

DOM事件流三个阶段

1.事件捕获:当鼠标触发DOM事件时,浏览器会从根节点由外到内进行事件传播。即触发子元素的事件,父元素会通过事件捕获的方式优先触发父元素的事件。

2.目标阶段:正在处理事件。

3.事件冒泡:与事件捕获相反,浏览器会从子节点由内到外进行事件传播。

DOM事件流处理顺序:先捕获,再冒泡。

 

具体区别

通常在addEventListener方法的第三个参数中设置true则为事件捕获,false则为事件冒泡,默认为false。

html代码:

    <div id="div1">
        <div id="div2">
        </div>
    </div>

css代码:

<style>
    #div1 {
        width: 500px;
        height: 500px;
        border: 1px solid #ffffff;
        background: blanchedalmond;
    }

    #div2 {
        width: 200px;
        height: 200px;
        border: 1px solid #ffffff;
        background: blue;
    }
</style>

js代码:

<script>
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    div1.addEventListener('click', function () {
        console.log('div1--捕获');
    }, true);
    div2.addEventListener('click', function () {
        console.log('div2--捕获');
    }, true);
    div1.addEventListener('click', function () {
        console.log('div1--冒泡');
    });
    div2.addEventListener('click', function () {
        console.log('div2--冒泡');
    });
</script>

点击div2打印出的结果:

 由此可证上述结论即:捕获先于冒泡;对于捕获而言,外层先于内层(div1先于div2打印);对于冒泡而言,内层先于外层(div2先于div1打印)。

而我们期望的其实是对于冒泡事件,希望点击div2时仅仅只打印出div2--冒泡,修改js为:

<script>
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    div1.addEventListener('click', function (e) {
        console.log('div1--冒泡');
    });
    div2.addEventListener('click', function (e) {
        console.log('div2--冒泡');
        e.stopPropagation();
    });
</script>

此时点击div2打印的结果:

 兼容问题

IE浏览器9以下不支持e.stopPropagation();来取消冒泡事件,在IE浏览器10版本以上中已经解决该问题:

 为了更好的兼容各个浏览器版本,对e.stopPropagation()事件进行一个判断:

<script>
    let div1 = document.getElementById("div1");
    let div2 = document.getElementById("div2");
    div1.addEventListener('click', function (e) {
        console.log('div1--冒泡');
    });
    div2.addEventListener('click', function (e) {
        console.log('div2--冒泡');
        stopBubble();
    });
    function stopBubble (e) {
        if (e && e.stopPropagation) {
            e.stopPropagation();
        } else {
            window.event.cancelBubble = true;
        }
    }
</script>
原文地址:https://www.cnblogs.com/pipim/p/13424892.html