成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

一文搞懂JS中的事件冒泡機制

本篇文章聊聊事件冒泡,帶大家深入了解一下JS中的事件冒泡機制,希望對大家有所幫助!

一文搞懂JS中的事件冒泡機制

1. 事件

在瀏覽器客戶端應用平臺,基本生都是以事件驅動的,即某個事件發生,然后做出相應的動作。

瀏覽器的事件表示的是某些事情發生的信號。事件的闡述不是本文的重點,尚未了解的朋友,可以自行百度 進行了解,這將有助于更好地理解以下的內容 。

2.冒泡機制

什么是冒泡呢?

下面這個圖片大家應該心領神會吧,氣泡從水底開始往上升,由深到淺,升到最上面。在上升的過程中,氣泡會經過不同深度層次的水。

一文搞懂JS中的事件冒泡機制

相對應地:這個氣泡就相當于我們這里的事件,而水則相當于我們的整個dom樹;事件從dom 樹的底層 層層往上傳遞,直至傳遞到dom的根節點。

簡單案例分析

下面通過一個簡單的例案例來闡述冒泡原理:

定義一個html, 里面有三個簡單的dom 元素:div1,div2, span,div2包含span,div1 包含div2;而它們都在body 下:

<body id="body"> 	<div id="box1" class="box1"> 		<div id="box2" class="box2"> 			<span id="span">This is a span.</span> 		</div> 	</div> </body>

界面原型如下:

一文搞懂JS中的事件冒泡機制

在這個基礎上,我們實現下面的功能:

a、 body添加 click 事件監聽,當body捕獲到event事件時,打印出事件發生的時間和 觸發事件的節點信息:

<script type="text/javascript"> 	window.onload = function() { 		document.getElementById("body").addEventListener("click",eventHandler); 	} 	function eventHandler(event) { 		console.log("時間:"+new Date(event.timeStamp)+" 產生事件的節點:" + event.target.id +"  當前節點:"+event.currentTarget.id); 	} </script>

當我們依次點擊"This is span",div2,div1,body后,輸出以下信息:

一文搞懂JS中的事件冒泡機制

分析以上的結果:

無論是body,body 的子元素div1,還是 div的子元素div2,還有 span, 當這些元素被點擊click時,都會產生click事件,并且body都會捕獲到,然后調用相應的事件處理函數。就像水中的氣泡從底往上冒一樣,事件也會往上傳遞。

事件傳遞的示意圖如下所示:

一文搞懂JS中的事件冒泡機制

一般地,事件在傳遞過程中會有一些信息,這些是事件的組成部分:事件發生的時間+事件發生的地點+ 事件的類型+事件的當前處理者+其他信息

一文搞懂JS中的事件冒泡機制

完整的html代碼如下:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script type="text/javascript" src="js/jquery-1.11.0.js"></script> <title>Insert title here</title> <style type="text/css"> .box1 { 	border: green 40px solid; 	width: 300px; 	height: 300px; 	margin: auto; }   .box2 { 	border: yellow 40px solid; 	width: 220px; 	height: 220px; 	margin: auto; }   span { 	position: relative; 	left: 50px; 	top: 50px; 	background-color: rgba(128, 128, 128, 0.22); } </style>   <script type="text/javascript"> 	window.onload = function() { 		document.getElementById("body").addEventListener("click",eventHandler); 	} 	function eventHandler(event) { 		console.log("時間:"+new Date(event.timeStamp)+" 產生事件的節點:" + event.target.id +"  當前節點:"+event.currentTarget.id); 	} </script>   </head> <body id="body"> 	<div id="box1" class="box1"> 		<div id="box2" class="box2"> 			<span id="span">This is a span.</span> 		</div> 	</div> </body> </html>

b、終止事件的冒泡

我們現在想實現這樣的功能,在div1 點擊的時候,彈出 "你好,我是最外層div。",點擊div2 的時候,彈出 "你好,我是第二層div";點擊span 的時候,彈出"您好,我是span。"。

由此我們會有下面的javascript片段:

<script type="text/javascript"> 	window.onload = function() { 		document.getElementById("box1").addEventListener("click",function(event){ 			alert("您好,我是最外層div。"); 		}); 		document.getElementById("box2").addEventListener("click",function(event){ 			alert("您好,我是第二層div。"); 		}); 		document.getElementById("span").addEventListener("click",function(event){ 			alert("您好,我是span。"); 		}); 	} </script>

預期上述代碼會單擊span 的時候,會出來一個彈出框 "您好,我是span。" 是的,確實彈出了這樣的對話框:

一文搞懂JS中的事件冒泡機制

然而,不僅僅會產生這個對話框,當點擊確定后,會依次彈出下列對話框:

一文搞懂JS中的事件冒泡機制 一文搞懂JS中的事件冒泡機制

這顯然不是我們想要的! 我們希望的是點誰顯示誰的信息而已。為什么會出現上述的情況呢? 原因就在于事件的冒泡,點擊span的時候,span 會把產生的事件往上冒泡,作為父節點的div2 和 祖父節點的div1也會收到此事件,于是會做出事件響應,執行響應函數。現在問題是發現了,但是怎么解決呢?

方法一:我們來考慮一個形象一點的情況:水中的一個氣泡正在從底部往上冒,而你現在在水中,不想讓這個氣泡往上冒,怎么辦呢?——把它扎破!沒了氣泡,自然不會往上冒了。類似地,對某一個節點而言,如果不想它現在處理的事件繼續往上冒泡的話,我們可以終止冒泡:

在相應的處理函數內,加入 event.stopPropagation() ,終止事件的廣播分發,這樣事件停留在本節點,不會再往外傳播了。修改上述的script片段:

<script type="text/javascript"> 	window.onload = function() { 		document.getElementById("box1").addEventListener("click",function(event){ 			alert("您好,我是最外層div。"); 			event.stopPropagation(); 		}); 		document.getElementById("box2").addEventListener("click",function(event){ 			alert("您好,我是第二層div。"); 			event.stopPropagation(); 		}); 		document.getElementById("span").addEventListener("click",function(event){ 			alert("您好,我是span。"); 			event.stopPropagation(); 		}); 	} </script>

經過這樣一段代碼,點擊不同元素會有不同的提示,不會出現彈出多個框的情況了。

方法二:事件包含最初觸發事件的節點引用 和 當前處理事件節點的引用,那如果節點只處理自己觸發的事件即可,不是自己產生的事件不處理。event.target 引用了產生此event對象的dom 節點,而event.currrentTarget 則引用了當前處理節點,我們可以通過這 兩個target 是否相等。

比如span 點擊事件,產生一個event 事件對象,event.target 指向了span元素,span處理此事件時,event.currentTarget 指向的也是span元素,這時判斷兩者相等,則執行相應的處理函數。而事件傳遞給 div2 的時候,event.currentTarget變成 div2,這時候判斷二者不相等,即事件不是div2 本身產生的,就不作響應處理邏輯。

<script type="text/javascript"> 	window.onload = function() { 		document.getElementById("box1").addEventListener("click",function(event){ 			if(event.target == event.currentTarget) 			{ 			    alert("您好,我是最外層div。"); 			} 		}); 		document.getElementById("box2").addEventListener("click",function(event){ 			if(event.target == event.currentTarget) 			{ 				alert("您好,我是第二層div。"); 			} 		}); 		document.getElementById("span").addEventListener("click",function(event){ 			if(event.target == event.currentTarget) 			{ 			    alert("您好,我是span。"); 				 			} 		}); 	} </script>

比較:

從事件傳遞上看:

  • 方法一在于取消事件冒泡,即當某些節點取消冒泡后,事件不會再傳遞;

  • 方法二在于不阻止冒泡,過濾需要處理的事件,事件處理后還會繼續傳遞;

優缺點:

  • 方法一缺點:為了實現點擊特定的元素顯示對應的信息,方法一要求每個元素的子元素也必須終止事件的冒泡傳遞,即跟別的元素功能上強關聯,這樣的方法會很脆弱。比如,如果span 元素的處理函數沒有執行冒泡終止,則事件會傳到p2 上,這樣會造成p2 的提示信息;

  • 方法二缺點:方法二為每一個元素都增加了事件監聽處理函數,事件的處理邏輯都很相似,即都有判斷 if(event.target == event.currentTarget),這樣存在了很大的代碼冗余,現在是三個元素還好,當有10幾個,上百個又該怎么辦呢?

還有就是為每一個元素都有處理函數,在一定程度上增加邏輯和代碼的復雜度。

我們再來分析一下方法二:方法二的原理是 元素收到事件后,判斷事件是否符合要求,然后做相應的處理,然后事件繼續冒泡往上傳遞;

既然事件是冒泡傳遞的,那可不可以讓某個父節點統一處理事件,通過判斷事件的發生地(即事件產生的節點),然后做出相應的處理呢?答案是可以的,下面通過給body 元素添加事件監聽,然后通過判斷event.target 然后對不同的target產生不同的行為。

將方法二的代碼重構一下:

<script type="text/javascript"> 	window.onload = function() { 		document.getElementById("body").addEventListener("click",eventPerformed); 	} 	function eventPerformed(event) { 		var target = event.target; 		switch (target.id) { 		case "span":  			alert("您好,我是span。"); 			break; 		case "div1": 			alert("您好,我是第二層div。"); 			break; 		case "div2": 			alert("您好,我是最外層div。"); 			break; 		} 	} </script>

結果會是點擊不同的元素,只彈出相符合的提示,不會有多余的提示。

通過以上方式,我們把本來每個元素都要有的處理函數,都交給了其祖父節點body 元素來完成了,也就是說,span,p2,p1 將自己的響應邏輯委托給body,讓它來完成相應邏輯,自己不實現相應邏輯,這個模式,就是所謂的事件委托。

下面是一個示意圖:

一文搞懂JS中的事件冒泡機制

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
国产专区一线二线三线品牌| 粗大挺进亲女H晓晓| XXXⅩ少妇少妇XXXX范冰冰| 97久久人人超碰超碰窝窝| 爆乳护士HD完整版在线播放| 国产AVXXXX无套内射| 国精产品一区一区三区| 久久久久人妻精品区一| 欧美精品做受XXX性少妇| 日本一线二线三线四线五线| 无码成人一区二区三区| 亚洲国产成人精品女人久久久| 亚洲熟妇无码A∨| 999精产国品一二三产区区| 成人av在线播放| 国产拍揄自揄免费观看| 久久久99精品成人片中文字幕| 男女猛烈激情XX00免费视频| 狠狠色综合网久久久久久| 久久人人爽人人爽人人片AV高请 | 国产亚洲欧美日韩二三线| 精品一区二区久久久久久久网站 | 任你躁久久精品6| 午夜无码片在线观看影院网址 | 四虎最新在线永久免费| 亚洲国产精品无码一线岛国| 1000部又爽又黄无遮挡的视频| 大JI巴好深好爽又大又粗视频| 国内精品久久人妻无码不卡| 奶头大他一口都含不住| 少妇熟女久久综合网色欲| 亚洲欧洲无卡二区视頻| JZZIJZZIJ在线观看亚洲| 亚洲AV无码成H人动漫网站| 国产乱理伦片在线观看夜| 国内少妇人妻丰满AV| 男人女人做爽爽18禁网站| 私はあなたのおさんです怎么读| 亚洲欧洲日产国码无码| 菠萝菠萝蜜免费播放视频| 黑人大荫道BBWBBB高潮潮喷| 欧美日韩免费观看| 亚洲AV永久无码精品一福利 | 亚洲国产精品无码一区二区三区| JZZIJZZIJ亚洲乱熟无码| 国内精品免费久久久久电影院97| 欧美人伦禁忌DVD| 亚洲AV成人网人人蜜臀| HEYZO中文字幕无码| 狠狠88综合久久久久综合网| 秋霞成人无码电影在线观看| 亚洲AV无码成人精品区蜜桃| 啊灬啊灬快点灬用力岳| 精品毛片高清一区二区三区| 日韩精品人妻系列无码专区| 亚洲综合色一区二区三区| 国产98色在线 | 日韩| 老师在办公室被躁在线观看| 忘忧草日本在线播放WWW| 3CE九色眼影人间水蜜桃| 国语高潮无遮挡无码免费看| 日产无人区一线二线三线观看| 亚洲伊人伊成久久人综合网| 国产激情久久久久影院| 欧美裸体XXXX极品少妇| 亚洲乱色伦图片区小说| 国产AⅤ无码专区亚洲AV综合网| 蜜臀av一区二区蜜臀AV免费| 亚洲AV美国AV产亚洲AV图片| 成年免费视频黄网站ZXGK| 久久亚洲AV成人无码精品| 小妖精好爽H快穿共妻| 白嫩的18SEX少妇HD| 老妇乱强伦XXXXX| 亚洲AV无码成H人在线观看| 成熟人妻AV无码专区| 免费又黄又爽又猛的毛片| 亚洲成AV人片不卡无苍井空| 丰满性熟妇ⅩXXOOOZZX| 欧美丰满少妇人妻精品| 夜夜未满十八勿进的爽爽影院| 国产九九99久久99大香伊| 日本黄色网址日本| 50岁毛多熟女一区二区三区| 精品亚洲国产成人AV制服| 无码少妇一区二区三区浪潮av| 槽溜2021入口一二三四| 免费人成激情视频在线观看冫| 亚洲精品无码久久久| 国产成人免费无码AV在线播放| 欧洲RAPPER潮水太多| 中国老太太WBBHD| 精品久久8X国产免费观看| 无码人妻一区二区三区免费手机| 成人一区二区不卡久久久| 男女裸体下面进入的免费视频| 亚洲一区二区三区小说| 狠狠色丁香久久婷婷综合_中| 无码精品毛片波多野结衣| 房东天天吃我奶躁我| 人妻少妇AV中文字幕乱码| 51精产国品一二三产区| 久久伊人精品一区二区三区| 亚洲人成无码网站| 国内揄拍国内精品| 午夜人妻久久久久久久久| 国产成人精品亚洲精品| 日韓丨亞洲丨制服丨亂倫| 爱情岛网站亚洲禁18进入 | 精品人妻无码一区二区色欲产成人| 性VODAFONEWIFI另类| 国产精品人人妻人色五月| 双乳被一左一右的吸着| 吃警察爸爸的擎天柱视频| 日韩 无码 偷拍 中文字幕| 宝贝这么湿想要吗| 人妻少妇精品中文字幕AV蜜桃| JAPANESE娇小侵犯| 欧美一区二区三区久久综合| EEUSS影院WWW在线观看| 欧美性爱一区二区三区四区| 99热热久久这里只有精品68| 女人高潮被爽到呻吟在线观看| 18禁裸体动漫美女无遮挡网站| 蜜桃av中文字幕| 18一20岁GAYXXⅩ男| 男生把感叹号放进女生的括号| 撞击成熟美妇老师后臀| 嫩草欧美曰韩国产大片| AV一区二区三区| 人妻少妇精品无码专区二区| 波多野结衣TORRENT| 色噜噜精品一区二区三区| 国产成A人亚洲精V品无码性色| 挺进绝色校花的紧窄小肉| 国产激情一区二区三区视频免樱桃| 四虎影视在线观看2413| 国产精品乱子伦XXXX| 亚洲AⅤ精品无码一区二区| 黑人玩弄人妻1区二区| 亚洲人成色A777777在线观| 久久婷婷五月综合色和啪| 中国熟妇内谢69XXXXX软件| 男人用嘴添女人下身免费视频 | 亚洲日韩精品A∨片无码加勒比| 久久精品无码一区二区三区不卡 | 久久人人爽人人爽人人片AV高请| 中文字幕精品久久久久人妻| 欧美极品小妇另类xXXX性| 被老头玩弄邻居人妻中文字幕| 熟妇高潮一区二区精品午夜无码| 国产青草视频在线观看| 亚洲精品无码成人片| 妺妺窝人体色WWW国产馆在线 | 一本一道AV无码中文字幕﹣百度 | 18禁爆乳无遮挡免费观看日本动| 欧洲无人区码SUV| 国产AV一区二区三区天堂综合网 | 好大好厉害我接了一个顾客| 亚洲色成人网站WWW永久| 年轻漂亮的女邻居观看在线视频| 波多野结衣人妻厨房大战| 无码人妻AV一二区二区三区| 精品人无码一区二区三区| 8090私人影院| 深夜A级毛片免费视频| 狠狠躁夜夜躁人人躁婷婷视频 | 麻豆一二三四区乱码| 被下春药爽翻天按摩的人妻| 午夜人妻久久久久久久久| 久久久亚洲欧洲日产国码二区| А√天堂资源8在线官网地址| 凸凹人妻人人澡人人添医| 精品亚洲成AV人在线观看| AV夜夜躁狠狠躁日日躁| 天天澡夜夜澡狠狠久久| 九九九国产精品成人免费视频| AV无码东京热亚洲男人的天堂| 未满小14洗澡无码视频网站| 久久精品AⅤ无码中文字字幕| chinese炮打老熟女| 无码国产精品一区二区高潮| 久久久精品人妻一区二区三区蜜桃 | 色悠久久久久综合网国产| 京东影业JD008苏小小| ASS鲜嫩鲜嫩PICS| 无码人妻熟妇av又粗又大| 绿帽娇妻在卧室疯狂的呻吟| 放学后的特殊教育桃子移植| 亚洲精品中文字幕久久久久| 欧美一级 片内射黑人B| 国产熟女老妇300部MP4| 重囗味sm在线观看无码| 污污内射久久一区二区欧美日韩| 久久综合九色综合欧美婷婷| 东京热无码一区二区三区AV| 亚洲日韩精品无码AV一区二区三| 欧美亚洲国产一区二区三区| 黑人巨大精品欧美一区二区免费 | 漂亮人妻洗澡被强人人躁|