DOM事件機制

前言

轉載文,本文主要介紹DOM事件級別、DOM事件模型、事件流、事件代理和Event對象常見的應用,希望對你們有些幫助和啓發!

一、DOM事件級別

DOM級別一共可以分爲四個級別:DOM0級、DOM1級、DOM2級和DOM3級。而DOM事件分爲3個級別:DOM 0級事件處理,DOM 2級事件處理和DOM 3級事件處理。由於DOM 1級中沒有事件的相關內容,所以沒有DOM 1級事件。

1.DOM 0級事件

el.onclick=function(){}

當希望爲同一個元素/標籤綁定多個同類型事件的時候(如給上面的這個btn元素綁定3個點擊事件),是不被允許的。DOM0事件綁定,給元素的事件行爲綁定方法,這些方法都是在當前元素事件行爲的冒泡階段(或者目標階段)執行的。

2.DOM 2級事件

el.addEventListener(event-name, callback, useCapture)

event-name: 事件名稱,可以是標準的DOM事件

callback: 回調函數,當事件觸發時,函數會被注入一個參數爲當前的事件對象 event

useCapture: 默認是false,代表事件句柄在冒泡階段執行

IE9以下的IE瀏覽器不支持 addEventListener()和removeEventListener(),使用 attachEvent()與detachEvent() 代替,因爲IE9以下是不支持事件捕獲的,所以也沒有第三個參數,第一個事件名稱前要加on。

3.DOM 3級事件

在DOM 2級事件的基礎上添加了更多的事件類型。

UI事件,當用戶與頁面上的元素交互時觸發,如:load、scroll

焦點事件,當元素獲得或失去焦點時觸發,如:blur、focus

鼠標事件,當用戶通過鼠標在頁面執行操作時觸發如:dblclick、mouseup

滾輪事件,當使用鼠標滾輪或類似設備時觸發,如:mousewheel

文本事件,當在文檔中輸入文本時觸發,如:textInput

鍵盤事件,當用戶通過鍵盤在頁面上執行操作時觸發,如:keydown、keypress

合成事件,當爲IME(輸入法編輯器)輸入字符時觸發,如:compositionstart

變動事件,當底層DOM結構發生變化時觸發,如:DOMsubtreeModified

同時DOM3級事件也允許使用者自定義一些事件。

二、DOM事件模型和事件流

DOM事件模型分爲捕獲和冒泡。一個事件發生後,會在子元素和父元素之間傳播(propagation)。這種傳播分成三個階段。

(1)捕獲階段:事件從window對象自上而下向目標節點傳播的階段;

(2)目標階段:真正的目標節點正在處理事件的階段;

(3)冒泡階段:事件從目標節點自下而上向window對象傳播的階段。

DOM事件捕獲的具體流程

捕獲是從上到下,事件先從window對象,然後再到document(對象),然後是html標籤(通過document.documentElement獲取html標籤),然後是body標籤(通過document.body獲取body標籤),然後按照普通的html結構一層一層往下傳,最後到達目標元素。

而事件冒泡的流程剛好是事件捕獲的逆過程。

接下來我們看個事件冒泡的例子:

正如我們上面提到的onclick給元素的事件行爲綁定方法都是在當前元素事件行爲的冒泡階段(或者目標階段)執行的。

三、事件代理(事件委託)

由於事件會在冒泡階段向上傳播到父節點,因此可以把子節點的監聽函數定義在父節點上,由父節點的監聽函數統一處理多個子元素的事件。這種方法叫做事件的代理(delegation)。

1.優點

減少內存消耗,提高性能

假設有一個列表,列表之中有大量的列表項,我們需要在點擊每個列表項的時候響應一個事件

如果給每個列表項一一都綁定一個函數,那對於內存消耗是非常大的,效率上需要消耗很多性能。藉助事件代理,我們只需要給父容器ul綁定方法即可,這樣不管點擊的是哪一個後代元素,都會根據冒泡傳播的傳遞機制,把容器的click行爲觸發,然後把對應的方法執行,根據事件源,我們可以知道點擊的是誰,從而完成不同的事。

動態綁定事件

在很多時候,我們需要通過用戶操作動態的增刪列表項元素,如果一開始給每個子元素綁定事件,那麼在列表發生變化時,就需要重新給新增的元素綁定事件,給即將刪去的元素解綁事件,如果用事件代理就會省去很多這樣麻煩。

2.如何實現

接下來我們來實現上例中父層元素 #list 下的 li 元素的事件委託到它的父層元素上:

四、Event對象常見的應用

event. preventDefault()

如果調用這個方法,默認事件行爲將不再觸發。什麼是默認事件呢?例如表單一點擊提交按鈕(submit)跳轉頁面、a標籤默認頁面跳轉或是錨點定位等。

很多時候我們使用a標籤僅僅是想當做一個普通的按鈕,點擊實現一個功能,不想頁面跳轉,也不想錨點定位。


也可以通過JS方法來阻止,給其click事件綁定方法,當我們點擊A標籤的時候,先觸發click事件,其次纔會執行自己的默認行爲

接下來我們看個例子:輸入框最多隻能輸入六個字符,如何實現?

event.stopPropagation() & event.stopImmediatePropagation()

event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件處理程序被執行。上面提到事件冒泡階段是指事件從目標節點自下而上向window對象傳播的階段。

我們在例4的inner元素click事件上,添加event.stopPropagation()這句話後,就阻止了父事件的執行,最後只打印了'inner'。

stopImmediatePropagation 既能阻止事件向父元素冒泡,也能阻止元素同事件類型的其它監聽器被觸發。而 stopPropagation 只能實現前者的效果。我們來看個例子:

如上所示,使用 stopImmediatePropagation後,點擊按鈕時,不僅body綁定事件不會觸發,與此同時按鈕的另一個點擊事件也不觸發。

event.target & event.currentTarget

老實說這兩者的區別,並不好用文字描述,我們先來看個例子:

當我們點擊最裏層的元素d的時候,會依次輸出:

從輸出中我們可以看到,event.target指向引起觸發事件的元素,而event.currentTarget則是事件綁定的元素,只有被點擊的那個目標元素的event.target纔會等於event.currentTarget。也就是說,event.currentTarget始終是監聽事件者,而event.target是事件的真正發出者。

五、參考文章

DOM級別與DOM事件

DOM事件機制解惑

事件模型

JavaScript 事件委託詳解

JavaScript 事件的學與記:stopPropagation 和 stopImmediatePropagation

event.target和event.currentTarget的區別

原文:https://github.com/ljianshu/Blog/issues/44

最後:“相信有很多想學前端的小夥伴,今年年初我花了一個月整理了一份最適合2018年學習的web前端乾貨,從最基礎的HTML+CSS+JS到移動端HTML5等都有整理,送給每一位前端小夥伴,53763,1707這裏是小白聚集地,歡迎初學和進階中的小夥伴。”

祝大家早日學有所成,拿到滿意offer,快速升職加薪,走上人生巔峯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章