W3C下的冒泡和捕获机制

也是,好记性不如烂笔头。最近看到一个面试题目:

我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡。会执行几次事件,会先执行冒泡还是捕获。

按照现在的理解应该是两次,执行的顺序看你把哪个事件注册在前面了。(不知道题目理解对不对,感觉很笼统)。好吧还是看后面的吧!


<style type="text/css">
  #one{ 800px;height: 800px;background: blue;}
  #two{ 600px;height: 600px;background: white;}
  #three{ 400px;height: 400px;background: green;}
  #four{ 200px;height: 200px;background: yellow;}
</style>

<div id='one'>
  <div id='two'>
    <div id='three'>
      <div id='four'>
      </div>
    </div>
  </div>
</div>
<script type='text/javascript'>
  var one=document.getElementById('one');
  var two=document.getElementById('two');
  var three=document.getElementById('three');
  var four=document.getElementById('four');
  one.addEventListener('click',function(){
    alert('one');
  },false);
  two.addEventListener('click',function(){
    alert('two');
  },false);
  three.addEventListener('click',function(){
    alert('three');
  },false);
  four.addEventListener('click',function(){
    alert('four');
  },false);
</script>

 

我们开始以这个为例,当我们点击four时,结果会是four three two  one(这是在冒泡模式下);如果把false全改为true,然后点击four那么结果应该是one two three four(捕捉模式下)。这个应该很容易理解。那如果是下面这种呢

two.addEventListener('click',function(){
    alert('two 冒泡');
  },false);
  two.addEventListener('click',function(){
    alert('two 捕获');
  },true);
  
  three.addEventListener('click',function(){
    alert('three 冒泡');
  },false);
  
  three.addEventListener('click',function(){
    alert('three 捕获');
  },true);
  
  four.addEventListener('click',function(){
    alert('four 捕获');
  },true); 
  
  four.addEventListener('click',function(){
    alert('four 冒泡');
  },false); 

然后我点击three这个div应该打印的是什么。估计没有认真研究过的人,都会犹豫一下。

我们首先来看看事件的传播机制,借用一张图(大家可以看看这篇文章:https://www.w3.org/TR/DOM-Level-3-Events/#event-flow

事件传播是先进行捕捉再进行冒泡

事件响应分为三个阶段依次是:响应其他元素的捕获类型事件   当前元素注册事件(顺序与注册顺序一致)  响应其他元素冒泡事件

以上面的代码为例,首先会发生事件捕获,捕获会一直从最顶层的window对象,向里面延伸,直到最里面的那个元素id=three的div,也就是说捕获到这就停了,不会捕捉到id=four的div。那么这一路下来我们看看注册了多少发生在捕获阶段的事件,

就只有 id=two的div 一个 那么首先就会响应这个捕获事件。 id=two的div虽然也注册了一个冒泡事件,但是现在是不会执行的。然后捕捉跟踪到了元素本身,元素本身 (id=three的div)也都注册了捕获的事件和冒泡的事件,至于先执行哪一个,跟你的顺序有关,谁在前面先执行谁的,在这个例子中先响应冒泡事件,再响应捕获事件。捕获过程已经结束,要开始冒泡了,从该元素冒泡的window对象中,看看这条路线中,有多少冒泡类型的事件,只有 id=two的div有一个。所以整个过程打印的结果为

two 捕获-----three 冒泡----three 捕获----two 冒泡。

OK,写的仓促,比较粗糙,见谅。

原文地址:https://www.cnblogs.com/djlxs/p/5685518.html