Javasript學習筆記-Event事件

patrick_kibo發表於2018-11-22

Javasript學習筆記-Event事件
在前端開發過程中,頁面互動過程和事件機制密不可分,一直以來對於事件相關機制瞭解的不夠深刻,沒有好好進行了解,最近花了一點時間,梳理了一下事件機制以及相關常用的事件。

1. EventTarget

1.1 EventTarget物件

事件物件是事件的基礎,事件都不是獨立存在的,需要繫結在一個事件物件上,監聽物件的變化,當物件發生相關事件變化時觸發對應回撥。

window, document, Element都是EventTarget物件,一些非節點元素也是EventTarget,比如Ajax中的XMLHttpRequest物件

1.2 EventTarget物件方法

1.2.1 addEventListener

利用addEventListener可以給EventTarget增加Event事件,方法接受最多三個引數:

addEventListener(type, listener[, options/capture])

type: 事件型別,可以是瀏覽器支援的DomEvent,也可以是自己自定義的CustomEvent

listener: EventListenerUserAgent將事件傳送給EventListener的時候,會觸發listener物件中的handleEvent方法。由於歷史遺留,通常我們寫EventListener的時候第二個引數都是一個方法

eventTarget.addEventListener('click', ev => {})
複製程式碼

實際上等價於

eventTarget.addEventListener('click', {handleEvent: ev => {}})
複製程式碼

options/caputure: 第三個引數為可選,接受一個Object/Boolean,接受Object可以指定三個屬性:capture, once, passive

capture: 設定事件捕獲方式,預設為false,不使用捕獲,事件使用冒泡機制;設定為true,使用捕獲機制
once: 事件是否只觸發一次
passive: EventListener內部是否可以使用event.preventDefault(),設定為true的時候將不能使用,否則會提示錯誤資訊: Unable to preventDefault inside passive event listener invocation.

簡明一下瀏覽兩種事件觸發機制:冒泡和捕獲,冒泡是從內向外,捕獲是從外向內,借用網上經典的一個圖示來說明:

Javasript學習筆記-Event事件

PS:

  1. 老版本的IE瀏覽器使用attachEvent來作為addEventListener的替代方法
  2. 同一個事件多次繫結相同的函式並不會多次觸發 例如:
document.addEventListener('click', () => {console.log('click')})
document.addEventListener('click', () => {console.log('click')})
複製程式碼

這樣進行繫結,當點選頁面的時候會觸發兩次,但是如果按照以下方式進行繫結,則只會觸發一次

function click() {
  console.log('click')
}
document.addEventListener('click', click)
document.addEventListener('click', click)
複製程式碼

1.2.2 removeEventListener

移除繫結的EventListener物件

removeEventListener(type, listener[, useCapture])

同樣支援三個引數,第一個引數type為移除的事件型別,第二個引數為EventListener物件,必須和addEventListener新增的物件是同一個物件/方法,第三個引數為移除冒泡還是移除捕獲的事件

1.2.3 dispathEventListener

通常我們通過增加部分已經被定義的EventListener事件型別,例如:click, input等,直到使用者發生互動行為或EventTarget物件操作結束,觸發繫結的事件;除此以外,其實可以自定義EventTarget以及CustomEvent,並且利用dispatchEvent在任意時候手動觸發相關事件,例如:

let eventTarget = new EventTarget();
let event = new CustomEvent('myEvent', {detail: 'test' });
eventTarget.addEventListener('myEvent', () => {
    console.log('trigger event')
})
eventTarget.dispatchEvent(event);
複製程式碼

2. Events

2.1 Event

Event是所有Event物件的基類,包含了一些基礎的屬性

2.1.1 只讀屬性

bubbles: 判斷事件是否冒泡

cancelable: 判斷事件是否可以取消

composed: 判斷事件是否可以從ShadowDom傳遞到ShadowDom

currentTarget: 事件註冊的物件

defaultPrevented: 判斷事件是否執行了preventDefault()

eventPhase: 獲得事件觸發階段(0: Event.NONE, 1: Event.CAPTURE_PHASE捕獲階段, 2: Event.AT_TARGET到達觸發目標階段, 3: Event.BUBBLING_PHASE冒泡階段)

target:事件傳送的原始目標,和currentTarget區別在於,currentTarget是事件註冊的目標(有可能是target的父節點)

type: 觸發事件型別

timeStamp: 事件從建立成功後到觸發時所用的時間,單位毫秒

isTrusted: 判斷事件是使用者觸發還是非使用者觸發,true代表使用者觸發的事件

2.1.2 讀寫屬性

cancelBubble: Event.stopPropagation()歷史別名,設定為true以後會阻止事件冒泡

returnValue: 已經被preventDefault()替代,設定為false以後會阻止預設的事件

srcElement: IE舊版本瀏覽器中的target物件

2.1.3 方法

composedPath(): 獲取觸發事件路徑,會返回從targetWindow的事件路徑陣列

preventDefault(): 阻止預設的事件,例如input的預設事件是輸入,如果keyup/keydown事件使用了preventDefault(),則輸入框將無法輸入字元

stopImmediatePropagation(): 阻止其他type相同的事件的觸發,也就是同一個EventTarget的相同type事件只會觸發一個

stopPropagation():阻止事件的冒泡/捕獲

2.2 事件列舉(不完全列舉)

大部分的type事件有特定事件型別,不同的瀏覽器對具體事件型別支援的程度不一而同,列舉一些常用的事件子類,及會得到該子類的type型別

2.2.1 FocusEvent

blur: 失去焦點,不會冒泡

focusout: 失去焦點,支援冒泡

focus: 獲得焦點,不會冒泡

focusin: 獲得焦點,支援冒泡

2.2.2 MouseEvent

mouseenter: 滑鼠移入元素

mouseleave: 滑鼠移出元素

mouseover: 滑鼠移入元素/子元素(給父元素繫結以後,從父元素到子元素,或者從子元素到父元素都會觸發)

mouseout: 滑鼠移出元素/子元素

mousemove: 滑鼠在元素上持續移動

mousedown: 滑鼠在元素上點選

mouseup: 滑鼠在元素上釋放點選

click: 滑鼠點選(按下和釋放必須同時觸發),支援冒泡

dbclick: 滑鼠雙擊

contextmenu: 滑鼠右鍵開啟選單欄(監聽該事件後可以使用event.preventDefault()阻止開啟右鍵選單)

wheel: 滑鼠滾輪的滾動

2.2.3 CompositionEvent

有隻讀的data屬性,event.data可以獲取到正在輸入到字串

compositionend: 段落文字組成完成,比如:輸入法元件關閉

compositionstart: 文字輸入前觸發,不同於keydown,在輸入法控制元件開啟時候觸發(據說也支援語音識別開啟)

compositionupdate: 輸入法開啟後,文字輸入過程觸發

2.2.4 ErrorEvent

error: 資源載入失敗,頁面throw Error()可以進行捕獲

2.2.5 InputEvent

input: 對於<input type="text">, <textarea>, <select>元素值發生更改時同步觸發,對於<input type="radio">, <input type="checkbox">的元素,每次切換控制元件時觸發,contenteditable=true內的內容變更也會觸發

change: 不同於input,不一定每一次變化都會觸發,焦點遺失/會車等操作會觸發

2.2.6 KeyboardEvent

keydown: 鍵盤按鍵按下,無論是否產生字元都會觸發

keypress: 鍵盤按鍵按下,產生字元時觸發,因此ctrl,shift不產生字元都鍵位不會觸發

keyup: 鍵盤按鍵釋放

2.2.7 AnimationEvent

animationstart: CSS動畫開始

animationedn: CSS動畫結束

animationiteration: CSS動畫重複開始時觸發

2.2.8 TransitionEvent

*transtionstart: CSS中transition實際發生時,會在transition-delay後觸發,實驗性質事件

transitionend: CSS的transition結束的時候觸發

*transitionrun: transition-delay前觸發,實驗性質事件

2.2.9 ClipboardEvent

cut: 發生剪下時觸發,包括鍵盤快捷鍵和選單欄中的操作

copy: 發生複製時觸發,包括鍵盤快捷鍵和選單欄操作和document.execCommand('copy'),可以通過event.preventDefault()阻止複製,可以通過event.clipboardData.setData()getData()來獲取內容

paste: 發生貼上時觸發

2.2.10 TouchEvent

主要是使用在觸屏上的監聽

touchcancel: 一個或者多個觸點觸碰時,草畜了觸點支援的數量而被取消時觸發

touchend: 一個或多個觸點觸碰結束時觸發

touchemove: 一個或多個觸點移動的時候觸發

touchstart: 一個或多個觸點開始觸碰時觸發

2.2.11 PointerEvent

由於螢幕裝置的擴充套件,所以操作手段不在侷限於滑鼠,所以提供了一套和滑鼠操作相同的API,來支援類似的觸控事件

pointerover: 和mouseover等同

pointerenter: 和mouseenter等同

pointerdown: 和mousedown等同

pointermove: 和mousemove等同

pointerup: 和mouseup等同

pointerout: 和mouseout等同

pointerleave: 和mouseleave等同

2.2.12 DragEvent

拖動相關事件,其實分為了拖動元素事件和釋放區域事件兩類

拖動元素事件:

dragstart: 元素開始拖動

drag: 元素拖動中(每350ms觸發一次)

dragend: 元素拖動結束

釋放區域事件

dragenter: 拖動進入了drop目標區域,進入子節點也會反覆觸發

dragover: 元素在drop目標區域中移動(每350ms觸發一次),需要設定event.preventDefault()元素才能在該區域drop

dragleave: 拖動離開了drop目標區域,進入子節點也會觸發

drop: 元素在drop目標區域中拖動被釋放

2.2.13 MediaEvent

媒體播放相關事件,針對H5視訊<video>和音訊<audio>播放器的事件

durationchange: duration屬性更新

loadedmetadata: metadata屬性載入

loadeddata: media完成載入

canplay: 可以播放media的時候觸發(拖動進度條會觸發)

canplaythrough: 可以播放整個media時觸發(拖動進度條會觸發)

ended: media播放結束觸發

stalled: 請求media資料,但是劇沒有如預期到來時觸發

suspend: media請求掛起時觸發

play: media播放開始

playing: media播放中

pause: media暫停

waiting: 缺少資料載入

seeking: 時間進度條操作變動

seeked: 時間進度條操作變動停止

ratechannge: 播放速率改變

timeupdate: currentTime屬性更新(播放過程中時間變動)

volumechange: 音量調節

2.2.14 其他

select: 文字選中,只能監聽inputtextarea的選中(該事件和document.execCommand('copy')可以實現點選複製功能)

DOMContentLoaded: DOM載入完成,不會等待樣式,圖片渲染,Chrome中的devtool中Network中可以看到相關載入時間應該就是使用該監聽來處理的

beforeunload: 離開頁面前觸發,設定event.returnValue=true,將彈出提示訊息來確認是否關閉

offline/online: 在瀏覽器丟失網路/獲得網路時觸發

beforeprint: 準備列印/開啟列印預覽時觸發

afterprint: 開始列印/關閉列印預覽後時觸發

reset/submit: 表單重置/提交按鈕點選時觸發

fullscreenchange/resize/scroll:瀏覽器全屏/尺寸修改/滾動時觸發

hashChange: URL中#以及#後面的值發生變化的時候觸發,可能前端框架的路由機制可以用該監聽實現

readstatechange: documentreadyState發生變化的時候觸發,可以作為DomContentLoaded的替代

invalid: h5表單提交,繫結元素不符合規則的時候觸發(input元素可以設定驗證規則屬性,例如:required, max, min, pattern,可以通過偽類:invalid獲取到資料)

message: WebWorks資訊接受時觸發

2.3 CustomEvent

1.2.3 dispathEventListener 中提到了CustomEvent,可以根據自己的需求定義事件,並通過dispatchEvent來觸發繫結的自定義事件

3. 參考

MDN Event reference

相關文章