DOM事宜流中的冒泡和捕捉

这是本人的第一篇文章,迎接人人多多批评指正!

DOM2级事宜中addEventListener的实行机制,多个addEventListener同时增加时的实行前后规律:

W3C的DOM事宜触发分为三个阶段:
1.事宜捕捉阶段:即由最顶层元素(平常是从window元素最早,有的浏览器是从document最早,至于个中的差异我稍后会更新)最早,逐次进入dom内部,末了抵达目的元素,顺次实行绑定在其上的事宜;
2.处于目的阶段:检测机制抵达目的元素,按事宜注册递次实行绑定在目的元素上的事宜;
3.事宜冒泡阶段:从目的元素动身,向外层元素冒泡,末了抵达顶层(window或document),顺次实行绑定再其上的事宜。

在addEventListener中,应用第三个参数掌握其是从哪一个阶段最早,“true”是从捕捉阶段最早,而“false”则是跳过捕捉阶段,从冒泡阶段最早。

下面是一个简朴的例子:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>事宜流</title>
        <style type="text/css">
            #outer {
                width: 400px;
                height: 400px;
                background: #ccc;
            }
            #inner {
                width: 100px;
                height: 100px;
                background: #aaa;
            }
        </style>
    </head>
    <script type="text/javascript">
        window.onload = function() {
            var outer = document.getElementById("outer");
            var inner = document.getElementById('inner');

            outer.addEventListener("click", function() {
                alert("outer捕捉");
            }, true);

            inner.addEventListener("click", function() {
                alert("inner捕捉");
            }, true);

            outer.addEventListener("click",function() {
                alert("outer冒泡");
            }, false)
        }
    </script>
    <body>
        <div id="outer">
            <div id="inner"></div>
        </div>
    </body>
</html>

在这个例子里,假如我们点击内层元素inner,那末处于捕捉阶段的“outer捕捉”最早弹出,接下来是目的元素”inner捕捉”弹出,末了是处于冒泡阶段的”outer冒泡”弹出,即:“outer捕捉”–>”inner捕捉”–>”outer冒泡”。 纵然在代码里变更三个绑定事宜的递次,只需点击的是inner,这个实行递次就不会变。

那末题目来了,假如我们点击的是外层outer的话呢?

要邃晓这个题目,我们必需明白一点:目的事宜在哪一层,事宜流就在哪一层回流,纵然在outer事宜下另有很多子孙节点,事宜流都不会在outer以后往内流,此时,inner上的事宜不会被触发,因而在这段代码中,只会弹出“outer捕捉”和”outer冒泡”。

那末哪一个先弹呢?因为此时事宜处于第二阶段,即“处于目的阶段”,弹出递次取决的也不再是捕捉或冒泡,而是谁在代码中先注册,因而,在这段代码中,弹出的是:“outer捕捉”→”outer冒泡”。

综上所述,事宜在DOM中的实行递次为:外层捕捉事宜→内层捕捉事宜→先注册的目的事宜→后注册的目的事宜→内层冒泡事宜→外层冒泡事宜

让我们加深明白,看下面这个例子:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>事宜流</title>
        <style type="text/css">
            #box {
                width: 600px;
                height: 600px;
                background: yellow;
            }
            
            #outer {
                width: 400px;
                height: 400px;
                background: #ccc;
            }
            
            #inner {
                width: 100px;
                height: 100px;
                background: #aaa;
            }
        </style>
    </head>
    <script type="text/javascript">
        window.onload = function() {
            var outer = document.getElementById("outer");
            var inner = document.getElementById('inner');
            var oBox = document.getElementById('box');

            oBox.addEventListener("click", function() {
                alert('oBox冒泡');
            }, false)

            oBox.addEventListener("click", function() {
                alert('oBox捕捉');
            }, true)

            outer.addEventListener("click", function() {
                alert("outer捕捉");
            }, true);

            outer.addEventListener("click", function() {
                alert("outer冒泡");
            }, false);

            
            inner.addEventListener("click", function() {
                alert('inner冒泡')
            }, false);
            
            inner.addEventListener("click", function() {
                alert("inner捕捉");
            }, true);
            /*综上所述,事宜在DOM中的实行递次为:外层捕捉事宜→内层捕捉事宜→先注册的目的事宜→后注册的目的事宜→内层冒泡事宜→外层冒泡事宜*/
        }
    </script>

    <body>
        <div id="box">
            <div id="outer">
                <div id="inner"></div>
            </div>
        </div>
    </body>

</html>

在这段代码里,点击inner,box上的捕捉事宜最早实行,然后是outer上的捕捉事宜,然后是inner上先注册的事宜,然后是inner上后注册的事宜,末了是box上的冒泡事宜 弹出递次为:’oBox捕捉’→”outer捕捉”→’inner冒泡’→”inner捕捉”→”outer冒泡”→”oBox冒泡”。

补充一点,在ie8-中,因为addEventLister不起作用,我们运用attachEvent方法来绑定事宜,此时在第二阶段,也就是处于目的阶段,假如目的元素上绑定了两个事宜,那末其实行递次和addEventLister相反:谁后注册谁先实行。

假如dom0级事宜和dom2级事宜同时存在,那实行递次会是如何呢?

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>事宜流</title>
    <style>
        #box {
            width: 600px;
            height: 600px;
            background: yellow;
        }
            
        #outer {
            width: 400px;
            height: 400px;
            background: #ccc;
        }
            
        #inner {
            width: 100px;
            height: 100px;
            background: #aaa;
        }
    </style>
</head>
<body>
    <div id="box">
        <div id="outer">
            <div id="inner"></div>
        </div>
    </div>
</body>

<script type="text/javascript">
    window.onload = function () {

        var outer = document.getElementById("outer");
        var inner = document.getElementById('inner');
        var oBox = document.getElementById('box');

        oBox.addEventListener("click", function () {
            alert('oBox-Dom2冒泡');
        }, false);

        oBox.addEventListener("click", function () {
            alert('oBox-Dom2捕捉');
        }, true);
        outer.onclick = function(){
            alert("outer-dom0 click! ");
        }
        outer.addEventListener("click", function () {
            alert("outer-Dom2冒泡");
        }, false);
        
         
        outer.addEventListener("click", function () {
            alert("outer-Dom2捕捉");
        }, true);
    
        inner.addEventListener("click", function () {
            alert('inner-Dom2冒泡');
        }, false);

        inner.addEventListener("click", function () {
            alert("inner-Dom2捕捉");
        }, true);
    }
</script>

上面的例子中,我将outer的div在捕捉阶段和冒泡阶段都绑定了点击事宜,同时还在绑定了dom0级的点击事宜处置惩罚函数,这时候假如我们点击inner,我们会发明,事宜的实行递次是如许的oBox-Dom2捕捉–> outer-Dom2捕捉 –> inner-Dom2冒泡 –> inner-Dom2捕捉 –>outer-dom0 click!–>outer-Dom2冒泡 –> oBox-Dom2冒泡。

由此我们能够得出一个结论:当绑定dom0级事宜元素不是目的元素时,那末绑定dom0级事宜的处置惩罚是在冒泡阶段处置惩罚并按事宜注册的前后递次实行(W3C先注册的先实行) ,假如绑定dom0级事宜的元素是目的元素时,则不论是捕捉阶段绑定的处置惩罚函数照样冒泡阶段绑定的处置惩罚函数以及dom0级事宜处置惩罚函数,他们的实行递次都是根据注册的递次实行(W3C先注册的先实行) 。

    原文作者:Mary
    原文地址: https://segmentfault.com/a/1190000009482227
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞