[TOC]
DOM是和HTML文檔關(guān)聯(lián)的東西,其實(shí)很js沒(méi)有本質(zhì)的關(guān)系,只是js很多時(shí)候用來(lái)處理dom而已。
此外為了方便js操作dom,有一些框架庫(kù)可以選用,比如jquery。
# DOM0級(jí)事件處理方式:
通過(guò)javascript制定事件處理程序的傳統(tǒng)方式。就是將一個(gè)函數(shù)賦值給一個(gè)事件處理屬性。第四代web瀏覽器出現(xiàn),至今為所有瀏覽器所支持。優(yōu)點(diǎn),簡(jiǎn)單且具有跨瀏覽器的優(yōu)勢(shì)。
例:
~~~
var btn = document.getElementById("btn");
btn.onclick = function(){
alert(this.id);//this指定當(dāng)前元素btn
}
~~~
或者
`<input onclick="alert(1)" />`
刪除DOM0事件處理程序,只要將對(duì)應(yīng)事件屬性置為`null`即可。
~~~
btn.onclick = null;
~~~
缺點(diǎn):一個(gè)事件處理程序只能對(duì)應(yīng)一個(gè)處理函數(shù)。
* DOM2 是通過(guò)`addEventListener`綁定的事件,還有 IE 下的 DOM2 事件通過(guò)`attachEvent`綁定;
* DOM3 是一些新的事件,區(qū)別 DOM3 和 DOM2 的方法我感覺(jué)是 DOM3 事件有分大小寫的,DOM2 沒(méi)有;
# 事件流

IE的事件流是冒泡, 從里面往上面冒, netscape是從外部元素往內(nèi)部元素捕獲;
而**DOM2級(jí)的事件規(guī)定了事件流包含三個(gè)階段**包括:
* 1:事件捕獲
* 2:處于目標(biāo)階段
* 3:事件冒泡階段
(IE8以及更早版本不支持DOM事件流);
## 捕獲和冒泡
~~~
<div id="div1">
<div id="div2"></div>
</div>
<script>
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
div1.onClick = function(){
alert('1')
}
div2.onClick = function(){
alert('2');
}
</script>
~~~
> 當(dāng)點(diǎn)擊`div2`時(shí),會(huì)彈出兩個(gè)彈出框。在`ie8/9/10`、`chrome`瀏覽器,會(huì)先彈出”2” 再?gòu)棾?“1”,這就是事件冒泡:事件從最底層的節(jié)點(diǎn)向上冒泡傳播。
> 綁定在被點(diǎn)擊元素的多個(gè)事件是按照代碼順序發(fā)生,其他元素通過(guò)冒泡或者捕獲 “感知” 的事件,按照 W3C 的標(biāo)準(zhǔn),先發(fā)生捕獲事件,后發(fā)生冒泡事件。所有事件的順序是:其他元素捕獲階段事件 -> 本元素代碼順序事件 -> 其他元素冒泡階段事件 。
> `addEventListener`的第三個(gè)參數(shù)(`useCapture`參數(shù)默認(rèn)值為`false`)決定把事件發(fā)生時(shí)機(jī)是在捕獲階段(`true`)還是冒泡階段 (`false`)。
# DOM2級(jí)事件處理方式
DOM2級(jí)事件處理方式指定了,添加事件處理程序和刪除事件處理程序的方法。分別是:
```
addEventListener(eventName,func,isPuhuo);
removeEventListener(eventName,func,isPuhuo);
```
例如:
```
var btn = document.getElementById("btn");
handler = function(){
……
}
addEventListener("click",handler,false/true);
removeEventListener("click",handler,false/true);
```
參數(shù)分別是,事件處理屬性名稱,處理函數(shù),是否在捕獲時(shí)執(zhí)行事件處理函數(shù)。
注:
1. `eventName`的值均不含 `on`,例如注冊(cè)鼠標(biāo)點(diǎn)擊事件 eventName 為 `click`;
2. 處理函數(shù)中的 `this` 依然指的是指當(dāng)前dom元素( [addEventListener 回調(diào)中的 this 指向](https://www.jianshu.com/p/4943571dcac5));
3. 通過(guò) `addEventListener` 添加的事件處理程序,只能通過(guò) `removeEventListener` 來(lái)刪除,也就是說(shuō)通過(guò) `addEventListener` 添加的匿名函數(shù)將無(wú)法被刪除。
```
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function () {
alert(this.id);
}, false);
btn.removeEventListener("click", function () { //無(wú)效!
alert(this.id);
}, false);
```
## 事件對(duì)象

# IE中的DOM2級(jí)事件處理
IE 中的 DOM2 級(jí)事件處理使用了 `attachEvent` 和 `detachEvent` 來(lái)實(shí)現(xiàn)。這倆個(gè)方法接受倆個(gè)相同的參數(shù),事件處理名稱和事件處理函數(shù)。IE8 級(jí)更早版本只支持冒泡型事件,所以attachEvent添加的事件都會(huì)被添加到冒泡階段。
例如:
```
var btn = document.getElementById("btn");
btn.attachEvent("onclick",function(){
alert(this);//此處this是window
});
```
注意;通過(guò) `attachEvent` 添加的事件第一個(gè)參數(shù)是 `onclick` 而非標(biāo)準(zhǔn)事件中的 `click` 。在使用 `attachEvent` 方法和 DOM0 級(jí)事件處理程序的主要區(qū)別在于事件處理程序的作用域。采用DOM0級(jí)處理方式,事件處理程序會(huì)在其所屬元素的作用域內(nèi)運(yùn)行。使用 `attachEvent` ,事件處理程序會(huì)在全局作用域內(nèi)運(yùn)行,因此 `this` 等于 `window` 。
## 怎么移除匿名函數(shù)?
啊哈哈哈,我知道問(wèn)題出在哪了,也知道 `arguments.callee`(嚴(yán)格模式禁止) 到底是什么了!原來(lái)在函數(shù)內(nèi),`arguments.callee` 是指本函數(shù),也就是函數(shù)自身,所以以下會(huì)在控制臺(tái)輸出函數(shù) `aa`(toString 后也就是函數(shù)的代碼)。
```
(function aa() {
console.log(arguments.callee);
}());
```
而我要的函數(shù)不是這個(gè),而是綁定到 `click` 的函數(shù),所以代碼應(yīng)該改成這樣:
```
var i = 0;
function init() {
aabtn.addEventListener("click", function(e) { aa(arguments.callee); });
}
function aa(fun) {
tex.innerHTML = i++;
aabtn.removeEventListener("click", fun);
}
```
>參考:https://segmentfault.com/q/1010000002462675
### 3、DOM3事件
DOM瀏覽器中可能發(fā)生的事件有很多種,不同事件類型具有不同的信息,DOM3級(jí)事件規(guī)定了一下幾種事件:
UI事件,當(dāng)用戶與頁(yè)面上的元素交互時(shí)觸發(fā);
焦點(diǎn)事件,當(dāng)元素獲得或者失去焦點(diǎn)時(shí)觸發(fā);
鼠標(biāo)事件,當(dāng)用戶通過(guò)鼠標(biāo)在頁(yè)面上執(zhí)行操作時(shí)觸發(fā);
滾輪事件,當(dāng)使用鼠標(biāo)滾輪(或類似設(shè)備)時(shí)觸發(fā);
文本事件,當(dāng)在文檔中,輸入文本時(shí)觸發(fā);
鍵盤事件,當(dāng)用戶通過(guò)鍵盤在頁(yè)面上執(zhí)行操作時(shí)觸發(fā);
合成事件,當(dāng)為IME(Input Method Editor,輸入法編輯器)輸入字符時(shí)觸發(fā);
變動(dòng)事件,當(dāng)?shù)讓覦om結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā);
DOM3級(jí)事件模塊在DOM2級(jí)事件的基礎(chǔ)上重新定義了這些事件,也添加了一些新事件。包括IE9在內(nèi)的主流瀏覽器都支持DOM2級(jí)事件,IE9也支持DOM3級(jí)事件。
DOM中的事件模擬(自定義事件):
DOM3級(jí)還定義了自定義事件,自定義事件不是由DOM原生觸發(fā)的,它的目的是讓開(kāi)發(fā)人員創(chuàng)建自己的事件。
事件對(duì)象`event`下的屬性和方法:
```
因?yàn)楦鱾€(gè)瀏覽器的事件對(duì)象不一樣, 把主要的時(shí)間對(duì)象的屬性和方法列出來(lái);
bubble : 表明事件是否冒泡
cancelable : 表明是否可以取消冒泡
currentTarget : 當(dāng)前時(shí)間程序正在處理的元素, 和this一樣的;
defaultPrevented: false ,如果調(diào)用了preventDefualt這個(gè)就為真了;
detail: 與事件有關(guān)的信息(滾動(dòng)事件等等)
eventPhase: 如果值為1表示處于捕獲階段, 值為2表示處于目標(biāo)階段,值為三表示在冒泡階段
target || srcElement: 事件的目標(biāo)
trusted: 為ture是瀏覽器生成的,為false是開(kāi)發(fā)人員創(chuàng)建的(DOM3)
type : 事件的類型
view : 與元素關(guān)聯(lián)的window, 我們可能跨iframe;
preventDefault() 取消默認(rèn)事件;
stopPropagation() 取消冒泡或者捕獲;
stopImmediatePropagation() (DOM3)阻止任何事件的運(yùn)行;
//stopImmediatePropagation阻止 綁定在事件觸發(fā)元素的 其他同類事件的callback的運(yùn)行
IE下的事件對(duì)象是在window下的,而標(biāo)準(zhǔn)應(yīng)該作為一個(gè)參數(shù), 傳為函數(shù)第一個(gè)參數(shù);
IE的事件對(duì)象定義的屬性跟標(biāo)準(zhǔn)的不同,如:
cancelBubble 默認(rèn)為false, 如果為true就是取消事件冒泡;
returnValue 默認(rèn)是true,如果為false就取消默認(rèn)事件;
srcElement, 這個(gè)指的是target, Firefox下的也是srcElement;
```
# 參考
[史上最詳細(xì)的JavaScript事件使用指南](http://www.admin10000.com/document/6293.html)
[JavaScript 和事件](https://yujiangshui.com/javascript-event/)
小胡子的 [[解惑]JavaScript事件機(jī)制](http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html)
葉小釵的[【探討】javascript事件機(jī)制底層實(shí)現(xiàn)原理](http://www.cnblogs.com/yexiaochai/p/3477715.html)
- 步入JavaScript的世界
- 二進(jìn)制運(yùn)算
- JavaScript 的版本是怎么回事?
- JavaScript和DOM的產(chǎn)生與發(fā)展
- DOM事件處理
- js的并行加載與順序執(zhí)行
- 正則表達(dá)式
- 當(dāng)遇上this時(shí)
- Javascript中apply、call、bind
- JavaScript的編譯過(guò)程與運(yùn)行機(jī)制
- 執(zhí)行上下文(Execution Context)
- javascript 作用域
- 分組中的函數(shù)表達(dá)式
- JS之constructor屬性
- Javascript 按位取反運(yùn)算符 (~)
- EvenLoop 事件循環(huán)
- 異步編程
- JavaScript的九個(gè)思維導(dǎo)圖
- JavaScript奇淫技巧
- JavaScript:shim和polyfill
- ===值得關(guān)注的庫(kù)===
- ==文章==
- JavaScript框架
- Angular 1.x
- 啟動(dòng)引導(dǎo)過(guò)程
- $scope作用域
- $q與promise
- ngRoute 和 ui-router
- 雙向數(shù)據(jù)綁定
- 規(guī)范和性能優(yōu)化
- 自定義指令
- Angular 事件
- lodash
- Test
