1. 程式人生 > >js事件機制----捕獲與冒泡

js事件機制----捕獲與冒泡

先從事件繫結機制說起, 事件繫結機制通過繫結方法addEventListener()實現,

語法格式如下:

element.addEventListener(eventfunctionuseCapture)

引數值

引數 描述
event 必須。字串,指定事件名。

注意: 不要使用 "on" 字首。 例如,使用 "click" ,而不是使用 "onclick"。 

提示: 所有 HTML DOM 事件,可以檢視我們完整的 HTML DOM Event 物件參考手冊
function 必須。指定要事件觸發時執行的函式。 

當事件物件會作為第一個引數傳入函式。 事件物件的型別取決於特定的事件。例如, "click" 事件屬於 MouseEvent(滑鼠事件) 物件。
useCapture 可選。布林值,指定事件是否在捕獲或冒泡階段執行。

可能值:
  • true - 事件控制代碼在捕獲階段執行
  • false- false- 預設。事件控制代碼在冒泡階段執行

 

我們可以看到第三個引數是布林值, true表示在捕獲階段執行, 而false指在冒泡階段執行

所以什麼是 捕獲和冒泡?

捕獲(capture)和冒泡(bubble)是事件傳播過程中的兩個概念, 比如使用者單擊某個元素, 但由於元素處於父元素內, 該父元素又處於document物件中, document物件又處於window物件中, 因此該單擊事件實際發生在該元素, 父元素, document, window物件上, 而事件傳播過程就是瀏覽器決定依次觸發哪個物件的事件處理函式的過程.

DOM事件模型將事件傳播過程分為兩個階段: 捕獲階段和冒泡階段

在事件捕獲階段, 事件從最頂級的父元素逐層向內傳遞, 

在冒泡階段, 事件從事件發生的直接元素 , 逐層向父元素傳遞

這裡舉個簡單的例子:

點選孫子元素, 給body中的元素都新增點選事件並輸出觸發事件的物件id:

<!DOCTYPE html>
<html>
<head>
</head>
<body>
	<div id="父級">
        <div id="兒子">
            <div id="孫子" style="width:100px; height:100px; background-color:yellow">
            </div>
        </div>
    </div>
</body>
<script type="text/javascript">
    var a = document.getElementById('父級'),
        b = document.getElementById('兒子'),
        c = document.getElementById('孫子');
		a.addEventListener("click",show, true);
		b.addEventListener("click",show, true);
		c.addEventListener("click",show, true);
		console.log("前3為捕獲,後三個為冒泡");
		a.addEventListener("click",show, false);
		b.addEventListener("click",show, false);
		c.addEventListener("click",show, false);
		function show(even){	console.log(this.id);	}
</script>
</html>

其中兩條孫子輸出相同被摺疊了, 可以看到前三個是以捕獲順序, 第三個引數為true, 順序是從父親到孫子

後三個為false意思是冒泡順序, 順序是孫子到父級,即從內到外

實際上捕獲和冒泡時最外層和的元素並不是父級div,

捕獲時實際上是:

document-->html-->body-->父級div-->兒子div-->孫子div

冒泡時相反, 只不過body及以上沒新增事件並輸出, 所以在例子中沒顯現出來

所以用冒泡還是捕獲?

  對於事件代理來說,在事件捕獲或者事件冒泡階段處理並沒有明顯的優劣之分,但是由於事件冒泡的事件流模型被所有主流的瀏覽器相容,從相容性角度來說還是建議大家使用事件冒泡模型