也是,好记性不如烂笔头。最近看到一个面试题目:
我们给一个dom同时绑定两个点击事件,一个用捕获,一个用冒泡。会执行几次事件,会先执行冒泡还是捕获。
按照现在的理解应该是两次,执行的顺序看你把哪个事件注册在前面了。(不知道题目理解对不对,感觉很笼统)。好吧还是看后面的吧!
<style type="text/css">
#one{width: 800px;height: 800px;background: blue;}
#two{width: 600px;height: 600px;background: white;}
#three{width: 400px;height: 400px;background: green;}
#four{width: 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,写的仓促,比较粗糙,见谅。