事件淺談之事件冒泡

什麼是事件?

簡單來說,事件就是文檔或瀏覽器窗口發生的一些特定的交互瞬間。它最早時是用作分擔服務器運算負載的一種手段。後來DOM2級規範開始嘗試以一種符合邏輯的方式來標準化DOM事件。但是它並沒有規範所有的事件類型。後來,DOM3級又增強了DOM事件的API。我們所熟悉的BOM也支持一些事件, 但BOM事件長期並沒有規範,而且它支持的這些事件與DOM事件的關係也不太明確。使用事件有時複雜,有時相對簡單,難度會因爲需求的不同而不同。

事件流

事件流描述是從頁面中接收事件的順序。舉例:
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">
		div{
			padding:40px;
		}
		#div1{
			background:red;
		}
		#div2{
			background:blue;
		}
		#div3{
			background:green;
		}
	</style>
	<script type="text/javascript">
		window.onload = function(){
			var oDiv1= document.getElementById('div1');
			var oDiv2 = document.getElementById('div2');
			var oDiv3 = document.getElementById('div3');
			function fn (){
				alert(this.id)
			}
			oDiv1.onclick = fn;
			oDiv2.onclick = fn;
			oDiv3.onclick = fn;
		}
	</script>
</head>
<body>
	<div id="div1">
		<div id="div2">
			<div id="div3"></div>
		</div>
	</div>
</body>
</html>
效果展示:

當點擊綠色DIV時,會依次彈出三次三個Id,分別是Div1、Div2、Div3。並不是因爲他們的樣式表現,而是因爲html結構。如下代碼,結果同上:
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">
		div{
			padding:40px;
		}
		#div1{
			background:red;
		}
		#div2{
			background:blue;
		}
		#div3{
			background:green;
			position: absolute;
			top:300px;
		}
	</style>
	<script type="text/javascript">
		window.onload = function(){
			var oDiv1= document.getElementById('div1');
			var oDiv2 = document.getElementById('div2');
			var oDiv3 = document.getElementById('div3');
			function fn (){
				alert(this.id)
			}
			oDiv1.onclick = fn;
			oDiv2.onclick = fn;
			oDiv3.onclick = fn;
		}
	</script>
</head>
<body>
	<div id="div1">
		<div id="div2">
			<div id="div3"></div>
		</div>
	</div>
</body>
</html>
效果展示:
事件流包含兩個內容:
  1. 事件冒泡流
  2. 事件捕獲流

事件冒泡

先說一下,如果你點擊了某個按鈕,你也一定單擊了它的父級,父級的父級的父級......
拿上述的兩個例子,事件冒泡就是從事件開始的元素接收然後逐級向上傳播到window對象,
<div>--><body>--><html>-->document
所有現代瀏覽器都支持事件冒泡,但在具體實現上還是有一些差別。IE5.5及更早版本中的事件冒泡會跳過<html>元素,其他瀏覽器(IE9、Firefox、Chrome、Safari)則將事件一直冒泡到window對象。
首先,點擊oDiv1對象,然後觸發點擊事件,執行fn函數,然後傳播事件到它的父級oDiv2,如果oDiv2接收到一個點擊事件,那麼他就執行fn函數。(事件函數綁定:把一個函數與事件進行綁定,事件發生時執行函數)再傳播事件到oDiv2的父級oDiv3,如果oDiv3接收到一個點擊事件,那麼他就執行fn函數。
如果我們刪除
oDiv2.onclick = fn;
這行代碼,結果依然會彈出id爲Div1的id,那麼爲什麼會出現這種情況呢?因爲這種操作並沒影響oDiv2事件的發生和接收。會影響的只是事件發生以後要做的事情,即fn函數的執行,沒有綁定就不會執行,所以沒有顯示,但是它還是會把事件傳播給oDiv1,而oDiv1綁定了fn函數,所以,它彈出了oDiv1的id。

實例:下拉菜單

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">
		div{
			width:100px;
			height:200px;
			border:1px solid #000;
			background:pink;
			display: none
		}
	</style>
	<script type="text/javascript">
		window.onload = function(){
			var oBtn = document.getElementsByTagName('input')[0];
			var oDiv = document.getElementById('div')
			oBtn.onclick = function(){
				oDiv.style.display = "block";
			}
			document.onclick = function(){
				oDiv.style.display = 'none';
				
			}
		}
	</script>
</head>
<body>
	<input type="button" value="下拉按鈕"/>
	<div id="div"></div>
</body>
</html>
執行的時候按鈕怎麼都不會打開下拉列表,因爲當點擊按鈕的時候,觸發點擊事件,執行綁定函數:
function(){
	oDiv.style.display = "block";
}
正常情況下,下拉列表會出現,但是因爲下段代碼出現導致出現沒打開的現象
document.onclick = function(){
	oDiv.style.display = 'none';
				
}
實際上,下拉列表打開了,因爲時間太快所以並沒有看見,在看不見的時間裏,由於事件冒泡,oDiv把事件傳播到了它的父級的父級的父級即document對象,document對象恰好有綁定的函數,它的功能是把oDiv的display屬性值變爲none,所以,在看不見的時間裏,發生了確實發生的事情。爲了看的更明顯,可以加一個定時器。代碼如下:
document.onclick = function(){
				setTimeout(function(){
					oDiv.style.display = 'none';
				},1000)//1s之後執行
				
			}

如此看來,事件冒泡好像變得有點麻煩,缺點變得顯而易見,那麼爲什麼還要把它設置爲默認存在的呢?因爲他的優點不可忽略。

事件冒泡的優點:

假如事件冒泡不存在,我們還是實現如上效果:點擊按鈕下拉出現,點擊除按鈕以爲的任何元素下拉列表消失。
那麼,我們要做的是給頁面裏除按鈕以外的所有元素都加上點擊事件,這樣龐大的工程......像我是絕對做不下去的。但是如果有事件冒泡這種事件流,就很方便,我們 只需要給共同的父級加事件處理例如:body標籤,利用事件冒泡,用任何一個子元素都會把事件傳播給文檔,讓文檔去做這件事,會輕鬆很多。解決上面出現的問題,只需要阻止oBtn的事件冒泡就可以了。
event.cancleBubble = true;//默認情況爲false

實例:分享到



 
子級冒泡到父級

發佈了37 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章