DOM事件模型
- 從技術(shù)上來說,W3C的DOM標(biāo)準(zhǔn)并不支持上述最原始的添加事件監(jiān)聽函數(shù)的方式,這些都是在DOM標(biāo)準(zhǔn)形成前的事件模型。盡管沒有正式的W3C標(biāo)準(zhǔn),但這種事件模型仍然得到廣泛應(yīng)用,這就是我們通常所說的0級(jí)DOM。
<input type="button" id="myButton" onclick="alert('Button Click')" />
或
document.getElementById("myButton").onclick = function () {
alert("Button Click");
}
- 沒有1級(jí)DOM。DOM級(jí)別1于1998年10月1日成為W3C推薦標(biāo)準(zhǔn)。1級(jí)DOM標(biāo)準(zhǔn)中并沒有定義事件相關(guān)的內(nèi)容,所以沒有所謂的1級(jí)DOM事件模型。
- 在2級(jí)DOM中除了定義了一些DOM相關(guān)的操作之外還定義了一個(gè)事件模型 ,這個(gè)標(biāo)準(zhǔn)下的事件模型就是我們所說的2級(jí)DOM事件模型。
document.getElementById("myButton").addEventListener("click",
function (event) {
alert("Button Click");
console.log(event)
},
true)
// 回調(diào)的第一個(gè)參數(shù)是被觸發(fā)的事件對(duì)象,下面會(huì)簡(jiǎn)單介紹Event
DOM事件流
描述的就是從頁面中接受事件的順序。分有事件冒泡與事件捕獲兩種。
DOM事件流有三個(gè)階段:
- 事件捕獲階段
- 處于目標(biāo)階段
- 事件冒泡階段

可以通過addEventListener注冊(cè)事件時(shí)聲明捕獲還是冒泡階段,處于捕獲階段的事件會(huì)比冒泡階段先發(fā)生
相關(guān)API
-
Event(typeArg, eventInit)
- type
- target
- currentTarget
- clientX, clientY
- screenX, screenY
- CustomEvent(typeArg, eventInitDict)
-
addEventListener
- 注冊(cè)事件監(jiān)聽器
- 常用格式
target.addEventListener(type, listener, useCapture) - 回調(diào)listener的第一個(gè)參數(shù)可以是event對(duì)象
- useCapture表示注冊(cè)的是捕獲階段(true)還是冒泡階段(false,默認(rèn))
- stopPropagation,阻止事件傳遞
-
preventDefault,阻止事件默認(rèn)行為,下面兩個(gè)例子
- 阻止復(fù)選框被勾選
- 阻止input寫入內(nèi)容
簡(jiǎn)單說一下,Event的eventInit和CustomEvent的eventInitDict的區(qū)別
Event的eventInit有三個(gè)屬性可以選擇:bubbles表示是否可以冒泡,cancelable表示是否可以被取消,還有一個(gè)不常用的composed;
CustomEvent的eventInitDict,除了上面的bubbles和cancelable,還有一個(gè)details,它可以傳入你自定義的一些數(shù)據(jù),供給注冊(cè)事件監(jiān)聽器時(shí)在回調(diào)里面可以調(diào)用的一些數(shù)據(jù)
重點(diǎn)解析
bubbles
默認(rèn)為false,當(dāng)為false時(shí)不發(fā)生事件冒泡,也就是說,如果注冊(cè)的事件監(jiān)聽器是冒泡階段捕獲的話,將不會(huì)發(fā)生
var button = document.getElementById('clickMe');
var myEvent = new CustomEvent('demoEvent', {
bubbles: false,
cancelable: false,
detail: {
index: 'hello demo'
}
})
button.addEventListener('click', function () {
console.log('1. You click Button')
button.dispatchEvent(myEvent)
}, true);
document.body.addEventListener('demoEvent', function () {
console.log('2. You click body')
}, false);
document.addEventListener('demoEvent', function (e) {
console.log('3. You click document')
}, true);
window.addEventListener('demoEvent', function (e) {
console.log('4. You click window')
}, false);
上面的2和3不會(huì)發(fā)生,因?yàn)槭录emoEvent的bubbles是false,事件沒有冒泡階段
cancelable
如果該事件的 cancelable 屬性為 false, 則該事件的監(jiān)聽器無法阻止默認(rèn)行為, 調(diào)用preventDefault() 將產(chǎn)生錯(cuò)誤
自定義事件
邏輯如下:
- 新建一個(gè)事件對(duì)象,Event或者CustomEvent都行,但是變量名不要取event,因?yàn)樵诨卣{(diào)里會(huì)因?yàn)樽饔糜騿栴}被屏蔽
- 用一個(gè)節(jié)點(diǎn)對(duì)象發(fā)起事件(dispatch),該節(jié)點(diǎn)就算是事件流里的目標(biāo)對(duì)象
- 在事件流里的所有注冊(cè)了該事件的節(jié)點(diǎn)對(duì)象,都會(huì)調(diào)用回調(diào)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Event Bubbling</title>
</head>
<body>
<button id="clickMe">Click Me</button>
</body>
</html>
<script>
var button = document.getElementById('clickMe');
var myEvent = new CustomEvent('demoEvent', {
bubbles: true,
cancelable: false,
detail: {
index: 'hello demo'
}
})
button.addEventListener('click', function () {
console.log('1. You click Button')
button.dispatchEvent(myEvent)
}, true);
document.body.addEventListener('demoEvent', function () {
console.log('2. You click body')
}, false);
document.addEventListener('demoEvent', function (e) {
console.log('3. You click document')
}, true);
window.addEventListener('demoEvent', function (e) {
console.log('4. You click window')
}, false);
</script>
參考
這篇博客是參考了很多博客和API文檔,總結(jié)出來的。
包括但不限于:
事件模型淺析
Event
CustomEvent
創(chuàng)建和觸發(fā) events