W3C下的冒泡和捕獲機制。到底是冒泡呢。還是捕獲呢。一個DOM元素綁定多個事件時如何執行。

在準備阿里前端面試的時候看到這麼一道題。

一個DOM元素綁定兩個事件,一個冒泡,一個捕獲,則事件會執行多少次,執行順序如何。

這導致了我對冒泡和捕獲又進一步深入的瞭解。(永遠都在發現自己知識匱乏的日子中度過人生真是好抓急啊。)

首先冒泡和捕獲是怎麼一回事。

簡單點說。冒泡就是從下往上,像魚吐泡,泡泡是從下往上升的,也就是DOM元素被觸法事件時(此時的dom元素爲目標元素),目標元素事件執行後,它的祖先元素所綁定的事件會向上順序執行。

如下代碼,有四個div嵌套元素,均綁定了click事件,addEventListener函數的第三個參數設置爲false說明不爲捕獲事件,即爲冒泡事件。該代碼執行結果如下:

點擊one元素,輸出one;

點擊two元素,輸出two one;

點擊three元素,輸出 three two one;

點擊four元素,輸出 four three two one;

<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>

而捕獲則相反。當觸發目標元素時,會從目標元素的最頂層的祖先元素事件往下執行到目標元素爲止。

將上面的代碼第三個參數均改爲true,則執行結果如下:

點擊one,輸出one;

點擊two,輸出one two;

點擊three,輸出one two three;

點擊four,輸出one two three four;

很明顯執行順序是不同的。

以上便是冒泡和捕獲的基本理解。

而在一篇原創翻譯中瞭解到W3C的執行順序是擇中的。即

任何發生在 w3c事件模型 中的事件,首是進入捕獲階段,直到達到目標元素,再進入冒泡階段。 

(原文鏈接:http://www.cnblogs.com/hh54188/archive/2012/02/08/2343357.html。)

不過就是這篇文中的例子只有兩個dom元素。測試時無法充分理解。我自己便增加了兩個元素來理解。

首先,無論是冒泡事件還是捕獲事件,元素都會先執行捕獲階段

仍然以上面的代碼爲例子,假設目標元素爲four,也就是four被點擊,執行結果是一樣,那麼它的執行過程呢?

其實過程就是,從four元素的最頂層的祖先開始向下判斷是否有捕獲事件的元素,即第三個參數爲true的綁定事件的元素。

從上往下,如有捕獲事件,則執行;一直向下到目標元素後,從目標元素開始向上執行冒泡元素,即第三個參數爲false的綁定事件的元素。(在向上執行過程中,已經執行過的捕獲事件不再執行,只執行冒泡事件。)

如下代碼:

此時點擊four元素,four元素爲目標元素,one爲根元素祖先,從one開始向下判斷執行。

one爲捕獲事件,輸出one;

two爲冒泡事件,忽略;

three爲捕獲時間,輸出three;

four爲目標元素,開始向上冒泡執行,輸出four;(從此處分爲兩部分理解較容易。)

three爲捕獲已執行,忽略;

two爲冒泡事件,輸出two;

one爲捕獲已執行,忽略。

最終執行結果爲:one three four two

(在這裏可能會有疑問,目標元素是什麼事件有區別嗎?我的測試結果是沒有區別的,無論目標元素是捕獲還是冒泡,在w3c下都是先從根元素執行捕獲到目標元素,再從目標元素向上執行。)

有疑問的話可以在這個例子上將其他三個元素作爲目標元素測試。

例如,three作爲目標元素,執行結果爲:one three two(因爲two是冒泡事件,在向下執行時沒有執行到。)

one.addEventListener('click',function(){
alert('one');
},true);
two.addEventListener('click',function(){
alert('two');
},false);
three.addEventListener('click',function(){
alert('three');
},true);
four.addEventListener('click',function(){
alert('four');
},false);
最後就是討論一個DOM元素綁定多個事件的執行過程。

執行次數:綁定了幾個事件便執行幾次。

如下代碼,two元素綁定了兩個不同事件,點擊two都會執行這兩個事件。而執行順序有所差異

1、如果two爲目標元素,目標元素的事情按順序執行,而其他元素根據W3C的標準執行,即先捕獲後冒泡。

點擊two執行結果:one(因爲是two的父元素支持捕獲事件所以先執行)  two,bubble  two,capture(順序執行,注意逗號不是間隔,是輸出內容。)

2、如果目標元素不是two,則two的兩個事件按先捕獲後冒泡觸發執行,也就是跟前面討論的執行過程是一樣的,只不過兩個事件都綁定在同一個DOM元素上。

點擊three執行結果:one two,capture three,bubble two,bubble

one.addEventListener('click',function(){
alert('one');
},true);
two.addEventListener('click',function(){
alert('two,bubble');
},false);
two.addEventListener('click',function(){
alert('two,capture');
},true);
three.addEventListener('click',function(){
alert('three,bubble');
},true);
four.addEventListener('click',function(){
alert('four');
},true);
發佈了25 篇原創文章 · 獲贊 12 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章