DOM事件和事件委托

1 DOM 事件模型(DOM 事件機(jī)制)

HTML DOM 允許 JavaScript 對(duì) HTML 事件作出反應(yīng)续担。JavaScript 能夠在事件發(fā)生時(shí)執(zhí)行暴构,比如當(dāng)用戶(hù)點(diǎn)擊某個(gè) HTML 元素時(shí)麻敌。JavaScript與HTML之間的交互是通過(guò)事件實(shí)現(xiàn)的诲宇。

事件由事件源孩革、事件類(lèi)型和事件處理程序三部分組成

事件執(zhí)行步驟:獲取事件源 => 注冊(cè)(綁定)事件 => 采用函數(shù)賦值形式添加事件處理程序

2 事件流

事件流描述了頁(yè)面接受事件的順序岁歉,IE 和 Netscape 開(kāi)發(fā)團(tuán)隊(duì)提出了幾乎完全相反的事件流方案,IE支持事件冒泡流膝蜈,Netscape 支持事件捕獲流锅移。2002年,W3C發(fā)布標(biāo)準(zhǔn)饱搏,規(guī)定瀏覽器應(yīng)該支持兩種調(diào)用方式非剃,開(kāi)發(fā)者自己選擇把函數(shù)放在捕獲階段還是冒泡階段。

2.1 事件捕獲

Netscape事件流被稱(chēng)作事件捕獲流推沸,規(guī)定為從外向內(nèi)找監(jiān)聽(tīng)函數(shù)的過(guò)程备绽。

過(guò)程實(shí)例:當(dāng)點(diǎn)擊div元素時(shí)券坞,觸發(fā)click事件順序:
document => html => body => div

在事件捕獲中,click事件首先由document元素捕獲疯坤,隨后沿著DOM樹(shù)向下傳播报慕,直到到達(dá)目標(biāo)元素。

由于舊版本瀏覽器不支持压怠,因此通常建議使用事件冒泡眠冈,特殊情況使用時(shí)間捕獲。


2.2 事件冒泡

IE事件流被稱(chēng)作事件冒泡流菌瘫,規(guī)定為從內(nèi)向外找監(jiān)聽(tīng)函數(shù)的過(guò)程蜗顽。

過(guò)程實(shí)例:當(dāng)點(diǎn)擊div元素時(shí),觸發(fā)click事件順序:
div => body => html => document

在事件冒泡中雨让,被點(diǎn)擊的元素div最先觸發(fā)click事件雇盖,然后,click事件沿著DOM樹(shù)一路向上栖忠,在經(jīng)過(guò)的每個(gè)節(jié)點(diǎn)上以此觸發(fā)崔挖,直至到達(dá)document對(duì)象

所有現(xiàn)代瀏覽器都支持事件冒泡,但實(shí)現(xiàn)方式存在部分變化庵寞,如IE5.5早期版本會(huì)跳過(guò)html元素狸相,直接從body到document,現(xiàn)代瀏覽器中的事件會(huì)一直冒到window

取消冒泡(阻止事件冒泡)

  • 捕獲不可以取消捐川,但冒泡可以
  • e.stopPropagation()可以中斷(取消)冒泡脓鹃,瀏覽器不在向上走
  • 一般用于封裝某些獨(dú)立組件

不可阻止默認(rèn)動(dòng)作

  • 阻止默認(rèn)動(dòng)作語(yǔ)法:e.preventDefault()
  • 所有冒泡皆可取消,但默認(rèn)動(dòng)作有的可以取消有的不能取消
  • MDN搜索scroll event古沥,看到 Bubbles(該事件是否冒泡) 和 Cancelable(開(kāi)發(fā)者是否可以阻止默認(rèn)事件)
  • 取消scroll滾動(dòng)事件
    不可取消默認(rèn)動(dòng)作瘸右,因?yàn)楝F(xiàn)有滾動(dòng)才有滾動(dòng)事件
    但可以阻止wheel和touchstart的默認(rèn)動(dòng)作,注意需要找準(zhǔn)滾動(dòng)條所在元素岩齿,同時(shí)用CSS讓滾動(dòng)條width:0;
    也可使用overflow:hidden;直接取消滾動(dòng)條,但此時(shí)JS仍然可以修改scrollTop


2.3 addEventListener()

W3C模型

  • 先捕獲(父 => 子)太颤,再冒泡(子 => 父)
  • 特例:當(dāng)只有一個(gè)div被監(jiān)聽(tīng)(不考慮父子同時(shí)被監(jiān)聽(tīng)),fn分別在捕獲階段和冒泡階段監(jiān)聽(tīng)click事件盹沈,用戶(hù)點(diǎn)擊的元素就是開(kāi)發(fā)者監(jiān)聽(tīng)的栋齿,則誰(shuí)先監(jiān)聽(tīng)誰(shuí)先執(zhí)行(2022年已修復(fù),變?yōu)橄炔东@再冒泡)
  • 注意e對(duì)象會(huì)被傳給所有監(jiān)聽(tīng)函數(shù)
  • 事件結(jié)束后襟诸,e對(duì)象就不存在了(其實(shí)是存在的瓦堵,只是變成了currentTarget = null,更多了解后面再討論歌亲,暫時(shí)認(rèn)為不存在了)菇用,如果需要繼續(xù)使用,可以使用變量保存const t = e.currentTarget

注意:關(guān)于targetcurrentTarget的區(qū)別:

  • e.target—用戶(hù)操作的元素
  • e.currentTarget—程序員監(jiān)聽(tīng)的元素
  • this就是e.currentTarget
  • 實(shí)例:div > span{文字}陷揪,用戶(hù)點(diǎn)擊文字時(shí)惋鸥,e.target就是span杂穷,e.currentTarget是div

事件綁定API

  • IE5*:
// 冒泡
father.attachEvent('onclick', fn)
  • 網(wǎng)景(Netscape ):
// 捕獲
father.addEventListener('click', fn)
  • W3C:
// bool處為布爾值,決定采用冒泡還是捕獲卦绣,
// 不填時(shí)默認(rèn)為false耐量,則使用冒泡
// 填true時(shí)為網(wǎng)景的捕獲
father.addEventListener('click', fn,bool)


3 事件委托

事件委托就是利用冒泡的原理,但事件觸發(fā)時(shí)滤港,把要做的事件委托給父元素(或父元素的父元素)來(lái)處理廊蜒,將事件加到父級(jí)上,通過(guò)判斷事件來(lái)源的子集溅漾,執(zhí)行相應(yīng)操作山叮,從而避免對(duì)特定每個(gè)節(jié)點(diǎn)添加事件監(jiān)聽(tīng)器,減少占用內(nèi)存空間添履,提升性能屁倔。

  • 事件委托利用事件冒泡,可以只使用一個(gè)事件處理程序來(lái)管理一種類(lèi)型的事件暮胧。
    實(shí)例
    情景:需要給100個(gè)按鈕添加點(diǎn)擊事件锐借。
    解決方法:監(jiān)聽(tīng)這100個(gè)按鈕的祖先,由于這100個(gè)按鈕都是祖先的后代往衷,所以他們的事件都會(huì)向上冒泡钞翔,最終都會(huì)由添加給祖先的函數(shù)來(lái)處理,只需要檢查具體子元素(event對(duì)象)的相應(yīng)屬性/內(nèi)容就可以確定炼绘,然后執(zhí)行相應(yīng)操作即可。

  • 需要監(jiān)聽(tīng)目前不存在的元素的點(diǎn)擊事件時(shí)妄田,也可以通過(guò)事件委托實(shí)現(xiàn)俺亮。
    解決方法:監(jiān)聽(tīng)目標(biāo)元素的祖先,等點(diǎn)擊的時(shí)候再查看是否是需要的監(jiān)聽(tīng)的元素即可

優(yōu)點(diǎn)

  • 減少頁(yè)面所需內(nèi)存疟呐,提升整體性能
  • 可以用于監(jiān)聽(tīng)動(dòng)態(tài)元素
  • 節(jié)省花在設(shè)置頁(yè)面事件處理程序上的時(shí)間(只用指定一個(gè)處理函數(shù)脚曾,節(jié)省DOM引用)
  • document 對(duì)象隨時(shí)可用,任何時(shí)候都可以給它添加事件處理程序启具,只要頁(yè)面渲染出可點(diǎn)擊的元素本讥,就可以無(wú)延遲地起作用

適用事件

最適合使用事件委托的事件包括:clickmousedown鲁冯、mouseup拷沸、keydownkeypress

主要事項(xiàng)

  • JS支持,也不支持事件薯演,DOM事件不屬于JS的功能撞芍,屬于瀏覽器提供的DOM的功能
  • JS只是調(diào)用了DOM提供的addEventListener而已
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市跨扮,隨后出現(xiàn)的幾起案子序无,更是在濱河造成了極大的恐慌验毡,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帝嗡,死亡現(xiàn)場(chǎng)離奇詭異晶通,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)哟玷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)狮辽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人碗降,你說(shuō)我怎么就攤上這事隘竭。” “怎么了讼渊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵动看,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我爪幻,道長(zhǎng)菱皆,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任挨稿,我火速辦了婚禮仇轻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘奶甘。我一直安慰自己篷店,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布臭家。 她就那樣靜靜地躺著疲陕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钉赁。 梳的紋絲不亂的頭發(fā)上蹄殃,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音你踩,去河邊找鬼诅岩。 笑死穷遂,一個(gè)胖子當(dāng)著我的面吹牛道偷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播前塔,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼膝藕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逮京!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起束莫,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤懒棉,失蹤者是張志新(化名)和其女友劉穎草描,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體策严,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡穗慕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妻导。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逛绵。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖倔韭,靈堂內(nèi)的尸體忽然破棺而出术浪,到底是詐尸還是另有隱情,我是刑警寧澤寿酌,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布胰苏,位于F島的核電站,受9級(jí)特大地震影響醇疼,放射性物質(zhì)發(fā)生泄漏硕并。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一秧荆、第九天 我趴在偏房一處隱蔽的房頂上張望倔毙。 院中可真熱鬧,春花似錦乙濒、人聲如沸陕赃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)么库。三九已至,卻和暖如春豌蟋,著一層夾襖步出監(jiān)牢的瞬間廊散,已是汗流浹背桑滩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工梧疲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人运准。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓幌氮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親胁澳。 傳聞我的和親對(duì)象是個(gè)殘疾皇子该互,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1 捕獲和冒泡 2002年,W3C發(fā)布標(biāo)準(zhǔn) 文檔名為DOM Level 2 Events Specificatio...
    盧盧2020閱讀 331評(píng)論 0 1
  • 點(diǎn)擊事件 第一部分.概念 給3個(gè)div分別添加事件監(jiān)聽(tīng)fnYe/fnBa/fnEr提問(wèn)一:點(diǎn)擊了誰(shuí)韭畸?點(diǎn)擊文字宇智,算不...
    珍惜時(shí)間小李閱讀 223評(píng)論 0 0
  • Get Started DOM事件○ 標(biāo)準(zhǔn)○ 術(shù)語(yǔ)○ addEventListener○ 取消冒泡○ 自定義事件 ...
    茜Akane閱讀 310評(píng)論 0 0
  • 捕獲與冒泡 從外向內(nèi)找監(jiān)聽(tīng)函數(shù)蔓搞,叫事件捕獲從內(nèi)向外找監(jiān)聽(tīng)函數(shù),叫事件冒泡 W3C事件模型 事件綁定API:addE...
    是周大俠啊閱讀 149評(píng)論 0 1
  • DOM事件與事件委托 1.綁定事件的幾種方式 直接在dom元素上面綁定 在JS中進(jìn)行綁定 3.事件監(jiān)聽(tīng)方式 add...
    雨溪灘閱讀 248評(píng)論 0 0