javascript 事件傳播與事件冒泡,W3C事件模型

jopen 8年前發布 | 17K 次閱讀 W3C JavaScript開發 JavaScript

說實話筆者在才工作的時候就聽說了什么"事件冒泡",弄了很久才弄個大概,當時理解意思是子級dom元素和父級dom元素都綁定了相同類型的事件,這時如果子級事件觸發了父級也會觸發,然后這就叫做"事件冒泡"。然而,事情要是這么簡單的話,相信筆者這時一定已經迎娶了白富美,當上了CEO。壞就壞在后來又聽說一個"事件傳播" ,尼瑪不是"事件冒泡"嗎,然后又聽說了"W3C事件模型"。。。到了最后筆者徹底心碎了,只能乖乖的當忙農了!!!

咱們先說說里面的術語," 事件捕獲 "、" 事件冒泡 "、" 事件傳播 "、" 事件注冊 "、" W3C事件模型 "

" 事件注冊 ":事件注冊有好多方式,大概有下面這些

1、直接在dom元素上加,這其實是很挫的方式,然并卵,現在仍然有好多淫在用

<input type="button" onclick="alert('打的好')" name="button" value="痛擊我啊">

2、使用js程序在dom元素對象上加"onxxx"的形式

<input type="button" id="btn"  name="button" value="痛擊我啊">

document.getElementById('btn').onclick = function(){alert('打的好');};

3、使用諸如'addEventListener'、'attachEvent'函數

var dom = document.getElementById('btn');
var hander = function(){alert('打的好');};
if(dom.addEventListener){
  dom.addEventListener('click', hander, false);//支持標準w3c瀏覽器專用
}else{
 dom.attachEvent('onclick', hander);//非標準w3c瀏覽器專用
}

4、逼格更加高點的"事件委托",意思就是委托別人幫助自己響應事件,如下

<div id="father" style="background: green;">
        我是父親啊</br> 
        呵呵啊</br> 
        <div id="son" style="background: blue;">
            我是兒子啊
        </div> 
    </div>
document.getElementById('father').onclick = function(event){
            event = event || window.event;
            var target = event.srcElement || event.target;
            if(target.getAttribute('id') === 'son'){ alert('你點擊了兒子!');}
        }

點擊"我是兒子啊"彈出框框,點擊"我是父親啊" 什么都沒有彈,當然了,你不僅可以委托父級元素,也可以委托和你無關的元素

" 事件冒泡 " 和 " 事件傳播 ":

兩個一起說了,是有歷史原因的,早期有兩冤家,網景和微軟,它倆啥都對著干,網景搞"事件傳播",微軟對著干搞"事件冒泡",這倆貨有啥區別了,網上有人專門畫了一張圖

"事件冒泡"就是那個綠色的箭頭,"事件傳播"就是那個紅色的箭頭

"事件冒泡"就從目標元素"td"一直冒到根"window", "事件傳播"就從根"window"一直傳到"td"元素, 是不是編程都反著干,真是冤家

這時候聯合國"w3c"來了, 這不行啊,不能由著他們亂搞啊,不然這天下不就亂了,但是這兩家伙實力比較強,又不能不考慮他們啊,于是W3C采用中和方案制定標準,規定" 任何事件首先向下傳播直到遇到目標元素,然后再向上冒泡返回 " ,這注意好這問題統一了,并且都照顧了大家,我這秘書長位置穩保!!!

所以,你上面看到了兩個函數"attachEvent" 和 "addEventListener", 其中"attachEvent"是IE8及其之前的IE瀏覽器專用,只支持"事件冒泡","addEventListener" 是所有支持

W3C標準事件模型的瀏覽器專用,即支持"事件冒泡" 又支持 "事件傳播"。那對應的取消事件綁定就是 "detachEvent"和"removeEventListener" 兩個函數了。那上面那個"event = event || window.event" 也是兼容瀏覽器用的了,因為IE8及其之前的IE瀏覽器不能直接獲取event對象,需要從window對象獲取。

那這個"事件傳播"與"事件冒泡" 有啥實際上的區別了,我們還是以一段代碼來證明(由于IE8及之前的瀏覽器只支持"事件冒泡",因此我們這里用chrome瀏覽器測試)

先HTML代碼

<div id="father" style="background: green;">
        我是父親啊</br> 
        呵呵啊</br> 
        <div id="son" style="background: blue;">
            我是兒子啊
        </div> 
    </div>

界面是

document.getElementById('father').addEventListener('click', function(){
            alert('我是父親!');
        }, true);//在事件傳播階段捕獲
        document.getElementById('son').addEventListener('click', function(event){
            alert('我是兒子!');
        }, true);//在事件傳播階段捕獲

點擊"我是兒子啊" 是不是會彈出兩次,然后我們換成下面這段再看會彈出幾次

document.getElementById('father').addEventListener('click', function(){
            alert('我是父親!');
            event.stopPropagation();
        }, true);
        document.getElementById('son').addEventListener('click', function(event){
            alert('我是兒子!');
        }, true);

這次只彈出了一次"我是父親" , "我是兒子" 那句沒有執行,這是啥原因了?

因為這里設定在事件傳播階段捕獲事件,事件是先傳播到'father'元素中的,在'father'元素中調用了'event.stopPropagation()'阻止事件進一步捕獲,因此事件將不再傳播到'son'元素中 ( 注意,好多淫把阻止事件傳播或者冒泡 與 阻止默認事件 弄混淆了, 阻止默認事件的函數為 'preventDefault' 和 'returnValue = false;', 一個W3C標準瀏覽器專用,一個IE8及之前版本的IE專用 )

再來看在事件冒泡階段進行捕獲,會是怎樣的結果,代碼如下

document.getElementById('father').addEventListener('click', function(){
            alert('我是父親!');
        }, false);
        document.getElementById('son').addEventListener('click', function(event){
            alert('我是兒子!');
         event.stopPropagation();
        }, false);    

這次再點擊"我是兒子啊" 只彈出了"我是兒子","我是父親" 沒有彈出,這是啥原因了?

因為上面代碼設定了在事件冒泡階段捕獲,事件先進入傳播階段 傳播到'fanther', 'son'  然后到達目標元素 'son', 然后按照W3C的規定 以 事件冒泡 方式返回,先是到達'son', 但是在'son'這里被阻止了,因此不再往上冒泡,只能捕獲'son'中的事件了

" 事件捕獲 ":看了上面那么多,鄙人覺得這個就不用解釋了吧

" W3C事件模型 ":這個,筆者貌似在上面也解釋了,不用說了吧

鄙人才疏學淺,有不足之處,歡迎補足!!!

來自: http://www.cnblogs.com/painsOnline/p/5106310.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!