事件

DOM 的事件操作(監(jiān)聽和觸發(fā)),都定義在EventTarget接口挖函。所有節(jié)點對象都部署了這個接口磷仰,其他一些需要事件通信的瀏覽器內置對象,比如XMLHttpRequest颁井,也部署了這個接口厅贪。
該接口主要提供三個實例方法。

  • addEventListener: 綁定事件
  • removeEventListener: 移除事件
  • dispatchEvent: 觸發(fā)事件

addEventListener為例

btn.addEventListener('click',function(){console.log(this)},false)

第三個參數默認為false雅宾,可省略养涮,指該事件只在冒泡階段觸發(fā);若為true,則為在捕獲階段眉抬。
addEventListener方法可以為針對當前對象的同一個事件贯吓,添加多個不同的監(jiān)聽函數。這些函數按照添加順序觸發(fā)蜀变,即先添加先觸發(fā)悄谐。
用隊列理解,先進先出库北。

  • 進:addEventListener
  • 出:removeEventListener

如果為同一個事件多次添加同一個監(jiān)聽函數爬舰,該函數只會執(zhí)行一次,多余的添加將自動被去除(不必使用removeEventListener方法手動去除)寒瓦。

注意情屹,removeEventListener方法移除的監(jiān)聽函數,必須是addEventListener方法添加的那個監(jiān)聽函數杂腰,而且必須在同一個元素節(jié)點屁商,否則無效。

div.addEventListener('click', function (e) {}, false);
div.removeEventListener('click', function (e) {}, false);

上面代碼中,removeEventListener方法無效蜡镶,因為監(jiān)聽函數不是同一個匿名函數。

監(jiān)聽函數

瀏覽器的事件模型恤筛,就是通過監(jiān)聽函數對事件做出反應官还。事件發(fā)生后,瀏覽器聽到了這個事件毒坛,就會執(zhí)行相應的監(jiān)聽函數望伦。這就是事件驅動編程模式的主要編程方式。
JavaScript 有三種方法煎殷,可以為事件綁定監(jiān)聽函數屯伞。

1. addEventListener (推薦這種)

所有 DOM 節(jié)點實例都有addEventListener方法,用來為該節(jié)點定義事件的監(jiān)聽函數豪直。

window.addEventListener('load', doSomething, false);

相比另外兩種有如下優(yōu)點:

  • 同一個事件可以添加多個監(jiān)聽函數劣摇。
  • 能夠指定在哪個階段(捕獲階段還是冒泡階段)觸發(fā)監(jiān)聽函數。
  • 除了 DOM 節(jié)點弓乙,其他對象(比如window末融、XMLHttpRequest等)也有這個接口,它等于是整個 JavaScript 統(tǒng)一的監(jiān)聽函數接口暇韧。

2. 元素節(jié)點的事件屬性

元素節(jié)點對象的事件屬性勾习,同樣可以指定監(jiān)聽函數。

window.onload = doSomething;

div.onclick = function (event) {
  console.log('觸發(fā)事件');
};

使用這個方法指定的監(jiān)聽函數懈玻,也是只會在冒泡階段觸發(fā)巧婶。

注意,這種方法與 HTML 的on-屬性的差異是涂乌,它的值是函數名doSomething艺栈,而不像后者,必須給出完整的監(jiān)聽代碼doSomething()骂倘。

同一個事件只能定義一個監(jiān)聽函數眼滤,也就是說,如果定義兩次onclick屬性历涝,后一次定義會覆蓋前一次诅需。因此,也不推薦使用荧库。

3. HTML 的 on- 屬性(不推薦)

<body onload="doSomething()">
<div onclick="console.log('觸發(fā)事件')">

上面代碼為body節(jié)點的load事件堰塌、div節(jié)點的click事件,指定了監(jiān)聽代碼分衫。一旦事件發(fā)生场刑,就會執(zhí)行這段代碼。

注意蚪战,這些屬性的值是將會執(zhí)行的代碼牵现,而不是一個函數铐懊。

一旦指定的事件發(fā)生,on-屬性的值是原樣傳入 JavaScript 引擎執(zhí)行瞎疼。因此如果要執(zhí)行函數科乎,不要忘記加上一對圓括號。

對象this贼急、currentTarget和target

在事件處理程序內部茅茂,對象this始終等于currentTarget的值,而target則只包含事件的實際目標太抓。如果直接將事件處理程序指定給了目標元素空闲,則this、currentTarget和target包含相同的值走敌。

1 var btn = document.getElementById("myBtn");
2 btn.onclick = function (event) {
3     alert(event.currentTarget === this); //ture
4     alert(event.target === this); //ture
5 };

這個例子檢測了currentTarget和target與this的值碴倾。由于click事件的目標是按鈕,一次這三個值是相等的悔常。如果事件處理程序存在于按鈕的父節(jié)點中影斑,那么這些值是不相同的。

1 document.body.onclick = function (event) {
2     alert(event.currentTarget === document.body); //ture
3     alert(this === document.body); //ture
4     alert(event.target === document.getElementById("myBtn")); //ture
5 };

當單擊這個例子中的按鈕時机打,this和currentTarget都等于document.body矫户,因為事件處理程序是注冊到這個元素的。然而残邀,target元素卻等于按鈕元素皆辽,以為它是click事件真正的目標。由于按鈕上并沒有注冊事件處理程序芥挣,結果click事件就冒泡到了document.body驱闷,在那里事件才得到了處理。

currentTarget始終是監(jiān)聽事件者空免,而target是事件的真正發(fā)出者空另。

注意,在jQuery提供的on方法中蹋砚,e.currentTarget與該方法接收的第二個參數有關扼菠,根據jQuery的文檔描述

如果省略selector或者是null,那么事件處理程序被稱為直接事件 或者 直接綁定事件 坝咐。每次選中的元素觸發(fā)事件時循榆,就會執(zhí)行處理程序,不管它直接綁定在元素上墨坚,還是從后代(內部)元素冒泡到該元素的
當提供selector參數時秧饮,事件處理程序是指為委派事件(事件委托或事件代理)。事件不會在直接綁定的元素上觸發(fā),但當selector參數選擇器匹配到后代(內部元素)的時候盗尸,事件處理函數才會被觸發(fā)柑船。jQuery 會從 event target 開始向上層元素(例如,由最內層元素到最外層元素)開始冒泡振劳,并且在傳播路徑上所有綁定了相同事件的元素若滿足匹配的選擇器椎组,那么這些元素上的事件也會被觸發(fā)。

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <style>
    li{
      padding: 5px;
      border: 1px solid red;
    }
    span{
      border: 1px solid #000;
    }
  </style>
</head>
<body>
  <ul>
    <li><span>hello 1</span></li>
    <li><span>hello 1</span></li>
    <li><span>hello 1</span></li>
    <li><span>hello 1</span></li>
  </ul>
  <script>
    let ul = document.querySelectorAll('ul')[0]
    let aLi = document.querySelectorAll('li')
    $('ul').on('click','li',function(e){
 
        console.log(e.target)   //  被點擊的元素
        console.log(e.currentTarget)   //  li   
        console.log(e.currentTarget === this)  // true
    })
  </script>
</body>
</html>

當li中含有子元素的時候历恐,e.target指的是觸發(fā)事件的元素,可能是span也可能是li专筷,此時的e.currentTarget指的是selector那個參數弱贼,也就是本例中的li。如果省略selector參數磷蛹,那么它和addEventListener中e.target和e.currentTarget是一致的吮旅。

事件委托

事件委托就是利用事件冒泡機制,指定一個事件處理程序味咳,來管理某一類型的所有事件庇勃。
舉個取快遞的例子:
公司的員工們經常會收到快遞。為了方便簽收快遞槽驶,有兩種辦法:一種是快遞到了之后收件人各自去拿快遞责嚷;另一種是委托前臺MM代為簽收,前臺MM收到快遞后會按照要求進行簽收掂铐。
很顯然罕拂,第二種方案更為方便高效,同時這種方案還有一種優(yōu)勢全陨,那就是即使有新員工入職爆班,前臺的MM都可以代替新員工簽收快遞。
這個例子之所以非常恰當形象辱姨,是因為這個例子包含了委托的兩層意思:首先柿菩,現(xiàn)在公司里的員工可以委托前臺MM代為簽收快遞,即程序中現(xiàn)有的dom節(jié)點是有事件的并可以進行事件委托雨涛;其次枢舶,新入職的新員工也可以讓前臺MM代為簽收快遞,即程序中新添加的dom節(jié)點也是有事件的镜悉,并且也能委托處理事件祟辟。

如果一個ul中有100li,每個li都需要處理click事件侣肄,我們可以遍歷所有l(wèi)i旧困,給它們添加事件處理程序,這并不是理想的解決方案。
事件委托怎么實現(xiàn)呢吼具?因為冒泡機制僚纷,既然點擊子元素時,也會觸發(fā)父元素的點擊事件拗盒。那么我們就可以把點擊子元素的事件要做的事情怖竭,交給最外層的父元素來做,讓事件冒泡到最外層的dom節(jié)點上觸發(fā)事件處理程序陡蝇,這就是事件委托痊臭。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市登夫,隨后出現(xiàn)的幾起案子广匙,更是在濱河造成了極大的恐慌,老刑警劉巖恼策,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸦致,死亡現(xiàn)場離奇詭異,居然都是意外死亡涣楷,警方通過查閱死者的電腦和手機分唾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狮斗,“玉大人绽乔,你說我怎么就攤上這事∏榱洌” “怎么了迄汛?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骤视。 經常有香客問我鞍爱,道長,這世上最難降的妖魔是什么专酗? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任睹逃,我火速辦了婚禮,結果婚禮上祷肯,老公的妹妹穿的比我還像新娘沉填。我一直安慰自己,他們只是感情好佑笋,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布翼闹。 她就那樣靜靜地躺著,像睡著了一般蒋纬。 火紅的嫁衣襯著肌膚如雪猎荠。 梳的紋絲不亂的頭發(fā)上坚弱,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音关摇,去河邊找鬼荒叶。 笑死,一個胖子當著我的面吹牛输虱,可吹牛的內容都是我干的些楣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼宪睹,長吁一口氣:“原來是場噩夢啊……” “哼愁茁!你這毒婦竟也來了?” 一聲冷哼從身側響起亭病,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤埋市,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后命贴,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡食听,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年胸蛛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片樱报。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡葬项,死狀恐怖,靈堂內的尸體忽然破棺而出迹蛤,到底是詐尸還是另有隱情民珍,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布盗飒,位于F島的核電站嚷量,受9級特大地震影響,放射性物質發(fā)生泄漏逆趣。R本人自食惡果不足惜蝶溶,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宣渗。 院中可真熱鬧抖所,春花似錦、人聲如沸痕囱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鞍恢。三九已至傻粘,卻和暖如春每窖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抹腿。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工岛请, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人警绩。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓崇败,卻偏偏與公主長得像,于是被迫代替她去往敵國和親肩祥。 傳聞我的和親對象是個殘疾皇子后室,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348