1. 程式人生 > 其它 >JS事件冒泡與事件捕獲

JS事件冒泡與事件捕獲

事件捕獲與事件冒泡:
  • 事件捕獲:由微軟公司提出,事件從文件根節點(Document 物件)流向目標節點,途中會經過目標節點的各個父級節點,並在這些節點上觸發捕獲事件,直至到達事件的目標節點;
  • 事件冒泡:由網景公司提出,與事件捕獲相反,事件會從目標節點流向文件根節點,途中會經過目標節點的各個父級節點,並在這些節點上觸發捕獲事件,直至到達文件的根節點。整個過程就像水中的氣泡一樣,從水底向上運動

W3C 為了統一標準,採用了一個折中的方式,即將事件捕獲與事件冒泡合併,也就是現在的“先捕獲後冒泡”

 

 

 

addEventListener的第三個引數

這個一個給事件繫結監聽函式的方法,它接收三個引數

element.addEventListener(event
, function, useCapture)

第一個引數是需要繫結的事件(字串,指定事件名,不要用on字首,使用click而不是使用onclick)
第二個引數指定事件觸發時執行的函式
第三個引數預設為false,指定事件流為事件冒泡,設為為true時指定為事件捕獲。

 

冒泡

//事件冒泡
<div  id="s1">s1
    <div id="s2">s2</div>
</div>
<script>
    s1.addEventListener("click",function(){
        console.log("s1冒泡事件
") }); s2.addEventListener("click",function(){ console.log("s2冒泡事件") }) </script> //結果 點選s1輸出結果:s1冒泡事件 點選s2輸出結果:s2冒泡事件,s1冒泡事件
  1. 當點選s1時,先觸發s1的點選事件,然後向上觸發直至document,上面沒有其他的點選事件了,所以只輸出“s1冒泡事件”這個結果。
  2. 當點選s2時,先觸發s2的點選事件,所以先打印出“s2冒泡事件”,然後向上觸發至s1,又打印出“s1冒泡事件”,再向上觸發直至document。

捕獲

//事件捕獲
<div id="s1">s1 <div id="s2">s2</div> </div> <script> s1.addEventListener("click",function(){ console.log("s1捕獲事件") },true); s2.addEventListener("click",function(){ console.log("s2捕獲事件") },true) </script> //結果 點選s1輸出結果:s1捕獲事件 點選s2輸出結果:s1捕獲事件,s2捕獲事件
  1. 當點選s1時,先觸發最外層document,然後向下觸發直至具體元素s1,只有s1上監聽了click事件,所以只輸出“s1捕獲事件”這個結果。
  2. 當點選s2時,先觸發最外層document,然後向下觸發s1的click事件,所以列印“s1捕獲事件”這個結果,然後繼續向下觸發到s2,又打印出“s2捕獲事件”。

5.事件委託

 

  1. 事件委託是利用事件冒泡的原理。
  2. 使用情況:當有多個類似的元素需要繫結事件時,一個一個去繫結既浪費時間,又不利於效能,這時候可以使用事件委託,給他們的一個共同父級元素新增一個事件函式去處理所有的事件情況。
<ul id="father">
   <li>1</li>
   <li>2</li>
   <li>3</li>
   <li>4</li>
   <li>5</li>
</ul>
<script>
   father.addEventListener("click",function(e){
       if(e.target!=father){
           console.log(e.target.innerText)
       }
   });
</script>

//結果
點選哪個li,就輸出那個的文字

因為採用的事件冒泡的事件流,所以當點選li元素時,向上觸發他們的父元素上的點選事件。
優點:
1、效能 不需要迴圈所有的元素一個個繫結事件
2、靈活 當有新的子元素時不需要重新繫結事件

取消冒泡事件:
w3c標準 event.stopPropagation(),但ie9以下版本不支援

scroll,mouseleave ,mouseenterfocus,blur,focus,change,submit,reset,select等事件不冒泡。
hover事件不能使用事件委託方式。(滑鼠移動到元素上