事件流的顺序

js 部分很简单,就是显示事件流的执行顺序。

window.onload = function(){
    var outA = document.getElementById("outA");  
    var outB = document.getElementById("outB");  
    var outC = document.getElementById("outC");  
    outA.addEventListener('click',function(){alert("bubble1");},false);
    outB.addEventListener('click',function(){alert("bubble2");},false);
    outB.addEventListener('click',function(){alert("capture2");},true);    
    outC.addEventListener('click',function(){alert("target");},true);
    outA.addEventListener('click',function(){alert("capture1");},true);
};

css用来渲染这三个 div

div#outA{
    width:400px; height:400px; background:#CDC9C9;position:relative;
}
div#outB{
    height:200; background:#0000ff;top:100px;position:relative;
}
div#outC{
    height:100px; background:#FFB90F;top:50px;position:relative;
}

结构更简单,三个div

<div id="outA">
    <div id="outB">
        <div id="outC">
        </div> 
    </div>
</div>

当点击divB的时候,我的理解应该输出是
capture1--capture2--bubble2--bubble1

为何实际结果是
capture1--bubble2--capture2--bubble1?

阅读 2.3k
2 个回答

1、window 往事件触发处传播,遇到注册的捕获事件会触发。
2、传播到事件触发处时触发注册的事件。
3、事件触发处往 window 传播,遇到注册的冒泡事件会触发。

divB正是事件触发处,而这时的事件触发顺序由事件的注册顺序决定。
你代码中是先注册了bubble2,后注册了capture2。你可以调换一下顺序再试一下。

又翻了翻《js高程》,事件流分为:事件捕获、处于目标、事件冒泡三个阶段。DOM2级事件标准明确要求捕获阶段不会涉及事件目标

所以点击的是outB时,虽然用true参数指定了捕获阶段的事件,但是却并不能让其在捕获阶段被触发,因为它本身是事件目标。《js高程》说:"IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的时间。结果,就是有两个机会在目标对象上面操作事件",看来事实上,高版本浏览器更加和标准相符了。

我在chrome上测试,此时outB上事件触发顺序只和绑定顺序相关了,你不妨将outB上的两个事件绑定交换下顺序,就会发现结果就又是capture1--capture2--bubble2--bubble1

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题