js事件冒泡和事件捕獲

一.事件流

事件纳胧,是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間镰吆。
事件流,描述的是頁面中接受事件的順序跑慕。
IE9万皿,chrome,F(xiàn)irefox核行,Opera牢硅,Safari均實現(xiàn)了DOM2級規(guī)范中定義的標(biāo)準(zhǔn)DOM事件,而IE8和IE8以下版本仍然保留專有的事件處理方式

1.事件冒泡

事件冒泡芝雪,即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收减余,然后逐級向上傳播。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #myDiv{
            width:100px;
            height:100px;
            background-color:#FF0000;
        }
    </style>
    <body>
        <div id="myDiv"></div>
    </body>  
<script type="text/javascript">
        var div=document.getElementById("myDiv");
        div.onclick=function(event){
            alert("div");
        };
        document.body.onclick=function(event){
            alert("body");
        };    
</script>  
</html>

點擊<div>惩系,將先輸出“div”位岔,再輸出“body”。
IE9蛆挫,chrome赃承,F(xiàn)irefox妙黍,Opera悴侵,Safari都支持事件冒泡,并將事件冒泡到window對象拭嫁。

2.事件捕獲

事件捕獲是由Netscape Communicator團隊提出來的可免,是先由最上一級的節(jié)點先接收事件抓于,然后向下傳播到具體的節(jié)點。當(dāng)用戶點擊了<div>元素浇借,采用事件捕獲捉撮,則click事件將按照document—><html>—><body>—><div>的順序進(jìn)行傳播。

若在<div>和<body>上都定義了click事件妇垢,如下:

        var div=document.getElementById("myDiv");    
        div.addEventListener("click",function(event){
            alert("div");
        },true);
        document.body.addEventListener("click",function(event){
            alert("body");
        },true);

點擊<div>巾遭,將先輸出“body”,再輸出“div”闯估。
IE9灼舍,chrome,F(xiàn)irefox涨薪,Opera骑素,Safari都支持事件捕獲,但是IE8和IE8以下的版本只支持事件冒泡刚夺。盡管DOM2規(guī)范要求事件應(yīng)該從document對象開始傳播献丑,但是現(xiàn)在的瀏覽器實現(xiàn)都是從window對象開始捕獲事件。

DOM事件流

"DOM2級事件”規(guī)定的事件流包含三個階段:事件捕獲階段侠姑,處于目標(biāo)階段和事件冒泡階段创橄。首先發(fā)生的是事件捕獲,然后是實際的目標(biāo)接收到事件莽红,最后階段是冒泡階段筐摘。以上面的HTML頁面為例,單擊<div>元素將按照下圖觸發(fā)事件:

<script type="text/javascript">
        var div=document.getElementById("myDiv");    
        div.onclick=function(event){
            alert("div");
        };
        document.body.addEventListener("click",function(event){
            alert("冒泡");
        },false);
        document.body.addEventListener("click",function(event){
            alert("捕獲");
        },true);
        
    </script>

點擊<div>船老,將先輸出“捕獲”咖熟,再輸出“div”,最后輸出“冒泡”柳畔。

二.事件處理程序

事件是用戶或瀏覽器自身執(zhí)行的某種動作馍管,而響應(yīng)某個事件的函數(shù)叫做事件處理程序。HTML事件處理程序薪韩、DOM0級事件處理程序和IE事件處理程序均以“on”開頭确沸,DOM2級事件處理程序不需要加“on”。

<div onclick="alert('我被點擊了')">我是通過屬性添加的事件</div>

DOM0級事件處理程序

通過Javascript指定事件處理程序的傳統(tǒng)方式俘陷,所有瀏覽器均支持罗捎。每個元素(包括window,document)都有自己的事件處理程序?qū)傩岳埽潜仨氃贒OM節(jié)點加載完之后才會有效桨菜。如下所示:

 var div=document.getElementById("myDiv");
    div.onclick=function(event){
        alert("div");
    };

使用DOM0級方法指定的事件處理程序被認(rèn)為是元素的方法,在元素的作用域中運行。this引用當(dāng)前元素倒得,如下:

 var div=document.getElementById("myDiv");
    div.onclick=function(event){
        alert(this.id);
    };

輸出“myDiv”泻红。
刪除通過DOM0級方法指定的事件處理程序:div.onclick=null;

DOM2級事件處理程序

IE9,chrome霞掺,F(xiàn)irefox谊路,Opera,Safari均實現(xiàn)了DOM2級事件處理程序菩彬,綁定事件方法addEventListener()接收三個參數(shù):事件名稱缠劝,事件處理函數(shù)和一個布爾值。布爾值為true骗灶,則表示在捕獲階段調(diào)用事件處理程序剩彬;如果為false,則表示在冒泡階段調(diào)用事件處理程序矿卑。addEventListener允許在同一個元素上添加多個事件處理程序喉恋,如下所示:

 var div=document.getElementById("myDiv");
 div.addEventListener("click",function(event){
        alert("冒泡");
    },false);
 div.addEventListener("click",function(event){
        alert("捕獲");
    },true);

先輸出“冒泡”,后輸出“捕獲”母廷,說明addEvenListener綁定的處理程序執(zhí)行順序和綁定順序相同轻黑。
通過DOM2級事件處理程序指定的方法,this也引用當(dāng)前元素琴昆,如下:

div.addEventListener("click",function(event){
        alert(this.id);
    },false);

輸出“myDiv”氓鄙。
刪除DOM2級事件處理程序,采用removeEventListener()业舍,刪除時傳入的參數(shù)必須和綁定時傳入的參數(shù)相同抖拦,不能傳入匿名函數(shù)。如下所示:

 var div = document.getElementById("myDiv");
    var handler=function(event){
        alert("delete");
    };
    div.addEventListener("click",handler,false);
    div.removeEventListener("click",handler,false);

IE事件處理程序

  var div = document.getElementById("myDiv");
    div.attachEvent("onclick", function(event) {
        alert("1");
    });
    div.attachEvent("onclick", function(event) {
        alert("2");
    });

IE9和IE10先輸出“1”舷暮,再輸出“2”态罪,而IE8和IE7先輸出“2”,再輸出“1”下面。
刪除IE事件處理程序复颈,采用detachEvent(),刪除時傳入的參數(shù)必須和綁定時傳入的參數(shù)相同沥割,不能傳入匿名函數(shù)耗啦。如下所示:

<script>
    var div = document.getElementById("myDiv");
    var handler = function(event) {
        alert("delete");
    };
    div.attachEvent("onclick",handler);
    div.detachEvent("onclick",handler);

</script>

總結(jié):attachEvent()采用冒泡方式,而addEventListener()可以采用冒泡或事件捕獲方式机杜。
先按由上往下的順序執(zhí)行事件捕獲的執(zhí)行程序帜讲,再執(zhí)行目標(biāo)元素的執(zhí)行程序,最后按由下往上的順序執(zhí)行冒泡事件椒拗。代碼如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #child {
            width: 100px;
            height: 100px;
            background-color: #FF0000;
        }
    </style>
</head>
<body>
<div id="myDiv"></div>
<div id="parent">
    <div id="child"></div>
</div>

</body>
<script>
    var parent = document.getElementById("parent");
    var child = document.getElementById("child");
    child.onclick = function(event) {
        alert("child");
    };
    document.body.addEventListener("click", function(event) {
        alert("body:捕獲");
    }, false);
    document.body.addEventListener("click", function(event) {
        alert("body:冒泡");
    }, true);
    parent.addEventListener("click", function(event) {
        alert("parent:冒泡");
    }, true);
    parent.addEventListener("onclick", function(event) {
        alert("parent:捕獲");
    });
</script>
</html>

輸出順序:body:捕獲—>parent:冒泡—>child—>parent:捕獲—>body:冒泡

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末似将,一起剝皮案震驚了整個濱河市获黔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玩郊,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枉阵,死亡現(xiàn)場離奇詭異译红,居然都是意外死亡,警方通過查閱死者的電腦和手機兴溜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門侦厚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拙徽,你說我怎么就攤上這事刨沦。” “怎么了膘怕?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵想诅,是天一觀的道長。 經(jīng)常有香客問我岛心,道長来破,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任忘古,我火速辦了婚禮徘禁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘髓堪。我一直安慰自己送朱,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布干旁。 她就那樣靜靜地躺著驶沼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪争群。 梳的紋絲不亂的頭發(fā)上商乎,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音祭阀,去河邊找鬼鹉戚。 笑死,一個胖子當(dāng)著我的面吹牛专控,可吹牛的內(nèi)容都是我干的抹凳。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼伦腐,長吁一口氣:“原來是場噩夢啊……” “哼赢底!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤幸冻,失蹤者是張志新(化名)和其女友劉穎粹庞,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洽损,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡庞溜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了碑定。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片流码。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖延刘,靈堂內(nèi)的尸體忽然破棺而出漫试,到底是詐尸還是另有隱情,我是刑警寧澤碘赖,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布驾荣,位于F島的核電站,受9級特大地震影響普泡,放射性物質(zhì)發(fā)生泄漏秘车。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一劫哼、第九天 我趴在偏房一處隱蔽的房頂上張望叮趴。 院中可真熱鬧,春花似錦权烧、人聲如沸眯亦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妻率。三九已至,卻和暖如春板祝,著一層夾襖步出監(jiān)牢的瞬間宫静,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工券时, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留孤里,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓橘洞,卻偏偏與公主長得像捌袜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炸枣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348