事件捕獲和事件冒泡

因為兼容ie琢融,一般使用事件冒泡

事件

js和瀏覽器交互通過事件實現(xiàn)

事件流

頁面元素接受事件的順序

事件捕獲

從根節(jié)點到目標節(jié)點

目標階段

到達目標階段

事件冒泡

從當前節(jié)點上溯到根節(jié)點

js的五種監(jiān)聽方式

1.HTML事件處理程序(冒泡)

事件處理程序中的代碼在執(zhí)行時,有權訪問到全局作用域中的任何代碼簿寂。
缺點:
*違反了html與js相分離原則
*元素一出現(xiàn)就出發(fā)了事件漾抬,js還沒加載,會報錯

<body onload="doSomething()">//不是doSomething常遂,雙引號里面是js的執(zhí)行
<div onclick="console.log('觸發(fā)事件')">//單引號不能改成雙引號纳令,因為里面是js,不能使用未經轉義的html

等同于:

el.setAttribute('onclick', 'doSomething()');

2.元素節(jié)點的事件屬性(冒泡)(DOM0級事件處理)

如果這個函數中存在this關鍵字克胳,那么this就會指向這個對象
缺點:1.一個事件只能定義一個監(jiān)聽函數平绩,意思是:如果定義兩次onclick屬性,后一次覆蓋前面一次
2.我們不能控制元素的事件流(捕獲or冒泡)毯欣。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <input id="myButton" type="button" value="click me">
    <script>
        var button = document.getElementById('myButton');
        function handler() {
            alert('click');
        }
        button.onclick = handler;
        // 移除事件
        // button.onclick = null;
    </script>
</body>
</html>

3.EventTarget.addEventListener(推薦)(DOM2級事件處理程序)

this同樣指向當前元素馒过,故函數在元素的作用域中執(zhí)行。

DOM2級事件”規(guī)定的事件流包括三個階段:事件捕獲階段酗钞、處于目標階段和事件冒泡階段腹忽。
此處詳細:https://wangdoc.com/javascript/events/eventtarget.html

“DOM2級事件”規(guī)定的事件流包括三個階段:事件捕獲階段、處于目標階段和事件冒泡階段砚作。

在DOM事件流中窘奏,實際的目標在捕獲階段不會接收事件。就是說在捕獲階段葫录,事件從document到html再到body后就停止了着裹。下一個階段是“處于目標”階段,于是事件在div中發(fā)生米同,并在事件處理中被看成是冒泡階段的一部分骇扇。然后,冒泡階段發(fā)生面粮。IE8及更早的版本不支持DOM事件流少孝,瀏覽器在捕獲階段觸發(fā)事件對象上的事件,結果就是有兩個機會在目標對象上面操作事件熬苍。

(1)*DOM2級事件定義了兩個方法:addEventListener()和removeEventListener()稍走。

*需要注意的是,通過addEventListener()指定的事件處理程序只能通過removeEventListener()移除柴底;
*同時婿脸,如果在addEventListener()中的第二個參數是一個匿名函數,則無法通過removeEventListener()移除柄驻,也沒有辦法移除狐树。

*而IE實現(xiàn)了與DOM中類似的兩個方法:attachEvent()和detachEvent(),這兩個方法直接收兩個參數鸿脓,第一個為事件名稱(注意事件名稱都有on前綴褪迟,例如click事件則為onclick)冗恨,第二個參數為事件處理程序函數。

function hello() {
  console.log('Hello world');
}

var button = document.getElementById('btn');
button.addEventListener('click', hello, false);//第三個參數false的時候是冒泡排序味赃,true的時候是捕獲

移除事件監(jiān)聽addEventListener:

div.addEventListener('click', listener, false);
div.removeEventListener('click', listener, false);//與addEventListener參數完全相同掀抹,并且第二個參數不能是匿名函數(會認為兩個匿名函數不是同一個)。

優(yōu)點:
*同一個事件可以添加多個監(jiān)聽函數心俗。
*能夠指定在哪個階段(捕獲階段還是冒泡階段)觸發(fā)監(jiān)聽函數傲武。
*除了 DOM 節(jié)點,其他對象(比如window城榛、XMLHttpRequest等)也有這個接口揪利,它等于是整個 JavaScript 統(tǒng)一的監(jiān)聽函數接口。

4.IE事件處理程序

IE事件處理程序中有類似與DOM2級事件處理程序的兩個方法:

*attachEvent()
*detachEvent()

 $btn.attachEvent('onclick', function() {
  alert('i am isaac');
});

它們都接收兩個參數:

i.事件處理程序名稱狠持。如onclick疟位、onmouseover,注意:這里不是事件喘垂,而是事件處理程序的名稱甜刻,所以有on。
ii.事件處理程序函數正勒。如function(){alert("clicked");}
(之所以沒有和DOM2級事件處理程序中類似的第三個參數得院,是因為IE8及更早版本只支持冒泡事件流。)

注意:
1.IE事件處理程序中attachEvent()的事件處理程序的作用域和DOM0與DOM2不同章贞,她的作
用域是在全局作用域中祥绞。因此,不同于DOM0和DOM2中this指向元素鸭限,IE中的this指向
window蜕径。

2.同樣,我們可以使用attachEvent()來給同一個元素添加多個事件處理程序败京。但是與DOM2
不同丧荐,事件觸發(fā)的順序不是添加的順序而是添加順序的相反順序。

3.同樣地喧枷,通過attachEvent()添加的事件處理程序必須通過detachEvent()方法移除,同樣
的弓坞,不能使用匿名函數隧甚。

4.支持IE事件處理程序的瀏覽器不只有IE瀏覽器,還有Opera瀏覽器渡冻。

5.跨瀏覽器事件處理程序

即先判斷DOM2級事件處理程序戚扳,再判斷IE事件處理程序,最后使用DOM0級事件處理程序族吻。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>跨瀏覽器事件處理程序</title>
</head>
<body>
    

    <button id="button">點我</button>

<script>
var EventUtil={
    addHandler:function(element,type,handler){
        if(element.addEventListener){
            element.addEventListener(type,handler,false);//注意:這里默認使用了false(冒泡)
        }else if(element.attachEvent){
            element.attachEvent("on"+type,handler);
        }else{
            element["on"+type]=handler;
        }
    },
    removeHandler:function(element,type,handler){
        if(element.removeEventListener){
            element.removeEventListener(type,handler,false);//注意:這里默認使用了false(冒泡)
        }else if(element.detachEvent){
            element.detachEvent("on"+type,handler);
        }else{
            element["on"+type]=null;
        }
    }
};

    function handler(){
        alert("clicked");
    }

    var button=document.getElementById("button");
    EventUtil.addHandler(button,"click",handler);
</script>
</body>
</html>
DOM0和DOM2區(qū)別

如果定義了兩個dom0級事件帽借,dom0級事件會覆蓋

dom2不會覆蓋珠增,會依次執(zhí)行

dom0和dom2可以共存,不互相覆蓋砍艾,但是dom0之間依然會覆蓋

事件委托

<ul id="color-list">
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
    <li>item4</li>
    <li>item5</li>
</ul>
<script>
    (function () {
        var colorList = document.getElementById("color-list");
        colorList.addEventListener('click', showColor, false);
        function showColor(e) {
            e = e || window.event;
            var target = e.target || e.srcElement;
            console.log(target.innerHTML)
        }
    })();
</script>

好處:
(1)將多個事件處理器減少到一個蒂教,因為事件處理器要駐留內存,這樣就提高了性能脆荷。
想象如果有一個100行的表格凝垛,對比傳統(tǒng)的為每個單元格綁定事件處理器的方式和事件代理(即table上添加一個事件處理器),不難得出結論蜓谋,事件代理確實避免了一些潛在的風險梦皮,提高了性能。
桃焕、
(2)如果新增其他子元素(a,span,div等)剑肯,直接修改事件代理的事件處理函數即可,不需要重新綁定處理器观堂,不需要再次循環(huán)遍歷让网。
比如增加一個元素,事件并沒有起效:

<script>
    (function () {
        var colorList = document.getElementById("color-list");
        var colors = colorList.getElementsByTagName("li");
        for (var i = 0; i < colors.length; i++) {
            colors[i].addEventListener('click', showColor, false);
        }
        ;
        function showColor(e) {
            e = e || window.event;
            var targetElement = e.target || e.srcElement;
            console.log(targetElement.innerHTML);
        }
        var li=document.createElement('li');
        li.innerText='123';
        colorList.append(li);
    })();

</script>

參照:
https://wangdoc.com/javascript/events/model.html
https://www.cnblogs.com/zhuzhenwei918/p/6139281.html#1
高級程序設計283頁開始

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末型将,一起剝皮案震驚了整個濱河市寂祥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌七兜,老刑警劉巖丸凭,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腕铸,居然都是意外死亡惜犀,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門狠裹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虽界,“玉大人,你說我怎么就攤上這事涛菠±蛴” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵俗冻,是天一觀的道長礁叔。 經常有香客問我,道長迄薄,這世上最難降的妖魔是什么琅关? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮讥蔽,結果婚禮上涣易,老公的妹妹穿的比我還像新娘画机。我一直安慰自己,他們只是感情好新症,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布步氏。 她就那樣靜靜地躺著,像睡著了一般账劲。 火紅的嫁衣襯著肌膚如雪戳护。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天瀑焦,我揣著相機與錄音腌且,去河邊找鬼。 笑死榛瓮,一個胖子當著我的面吹牛铺董,可吹牛的內容都是我干的。 我是一名探鬼主播禀晓,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼精续,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粹懒?” 一聲冷哼從身側響起重付,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凫乖,沒想到半個月后确垫,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡帽芽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年删掀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片导街。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡披泪,死狀恐怖,靈堂內的尸體忽然破棺而出搬瑰,到底是詐尸還是另有隱情款票,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布泽论,位于F島的核電站艾少,受9級特大地震影響,放射性物質發(fā)生泄漏佩厚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一说订、第九天 我趴在偏房一處隱蔽的房頂上張望抄瓦。 院中可真熱鬧潮瓶,春花似錦、人聲如沸钙姊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽煞额。三九已至思恐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間膊毁,已是汗流浹背胀莹。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留婚温,地道東北人描焰。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像栅螟,于是被迫代替她去往敵國和親荆秦。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內容

  • ??JavaScript 與 HTML 之間的交互是通過事件實現(xiàn)的。 ??事件吃媒,就是文檔或瀏覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,493評論 1 11
  • JavaScript 與 HTML 之間的交互是通過事件實現(xiàn)的瓤介。事件,就是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬...
    threetowns閱讀 344評論 0 0
  • 聲明:本文來源于http://www.webzsky.com/?p=731我只是在這里作為自己的學習筆記整理一下(...
    angryyan閱讀 7,018評論 1 6
  • 事件流 JavaScript與HTML之間的交互是通過事件實現(xiàn)的晓折。事件惑朦,就是文檔或瀏覽器窗口中發(fā)生的一些特定的交互...
    DHFE閱讀 831評論 0 3
  • DOM事件標準定義了兩種事件流,這倆種事件流有著顯著的不同并且可能對你的應用有著相當大的影響漓概。這倆種事件流分別是捕...
    郝特么冷閱讀 569評論 0 0