关于DOM2级事件的事件捕获和事件冒泡

花一天时间研究完了DOM2级事件中addEventListener的执行机制,做为开山第一帖,和你们讲讲多个addEventListener同时添加时的执行前后规律:
图片描述javascript

如图,你们都知道,W3c的DOM事件触发分为三个阶段:
①、事件捕获阶段,即由最顶层元素(通常是从window元素开始,有的浏览器是从document开始,至于其中的差异我稍后会更新)开始,逐次进入dom内部,最后到达目标元素,依次执行绑定在其上的事件
②、处于目标阶段,检测机制到达目标元素,按事件注册顺序执行绑定在目标元素上的事件。
③、事件冒泡阶段,从目标元素出发,向外层元素冒泡,最后到达顶层(window或document),依次执行绑定再其上的事件。java

在addEventListener中,利用第三个参数控制其是从哪一个阶段开始,“true”是从捕获阶段开始,而“false”则是跳过捕获阶段,从冒泡阶段开始。
看一个简单的例子:浏览器

<script type="text/javascript">
window.onload=function(){
    var outer = document.getElementById("outer");
    var inner = document.getElementById('inner');

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

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

 outer.addEventListener("click",
     function(){
        alert("3");
    }
,false)   
}
</script>

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

在这个例子里,若是咱们点击内层元素inner,那么处于捕获阶段的1最早弹出,接下来是目标元素2弹出,最后是处于冒泡阶段的3弹出,即:1,2,3.
即便在代码里变换三个绑定事件的顺序,只要点击的是inner,这个执行顺序就不会变。dom

那么问题来了,若是点击的是外层outer的话呢?spa

要明白这个问题,咱们必须明确一点:目标事件在哪一层,事件流就在哪一层回流,即便在outer事件下还有许多子孙节点,事件流都不会在outer以后往内流,此时,inner上的事件不会被触发,所以在这段代码中,只会弹出1和3。code

那么这两个数字哪一个先弹呢?因为此时事件处于第二阶段,即“处于目标阶段”,弹出顺序取决的也再也不是捕获或冒泡,而是谁在代码中先注册,所以,在这段代码中,弹出的是:1→3.blog

综上所述,事件在DOM中的执行顺序为:外层捕获事件→内层捕获事件→先注册的目标事件→后注册的目标事件→内层冒泡事件→外层冒泡事件事件

让咱们再看个例子来加深这个概念:图片

<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('1');
    },true)
    oBox.addEventListener("click",function(){
        alert('4');
    },false)
    

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

    
    inner.addEventListener("click",function(){
        alert('3.2')
    },false)
    

    inner.addEventListener("click", function(){
      alert("3.1");
     }, true);
    
}
</script>

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

在这段代码里,box上的捕获事件最早执行,而后是outer上的捕获事件,而后是inner上先注册的事件,而后是inner上后注册的事件,最后是box上的冒泡事件
弹出顺序为:1→2→3.2→3.1→4 ip

补充一点,在ie8-中,因为addEventLister不起做用,咱们使用attachEvent方法来绑定事件,此时在第二阶段,也就是处于目标阶段,若是目标元素上绑定了两个事件,那么其执行顺序和addEventLister相反:谁后注册谁先执行。

相关文章
相关标签/搜索