事件
事件冒泡
IE的事件流叫做事件冒泡(event bubbling),即事件開始時由具體的元素(文檔中嵌套層次深 的那個節(jié)點)接收,然后逐級向上傳播到較為不具體的節(jié)點(文檔)。
事件捕獲
事件處理程序(事件偵聽器)
HTML事件處理程序
<script type="text/javascript">
function showMessage(){
alert("Hello world!");
}
</script>
<input type="button" value="Click Me" onclick="showMessage()" />
DOM0級事件處理程序
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert("Clicked");
};
DOM2級事件處理程序
“DOM2級事件”定義了兩個方法,用于處理指定和刪除事件處理程序的操作:addEventListener() 和** removeEventListener()**。所有 DOM節(jié)點中都包含這兩個方法,并且它們都接受 3個參數(shù):要處理的事件名、作為事件處理程序的函數(shù)和一個布爾值。后這個布爾值參數(shù)如果是 true,表示在捕獲 階段調(diào)用事件處理程序;如果是 false,表示在冒泡階段調(diào)用事件處理程序。
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
alert(this.id);
}, false);
IE事件處理程序
IE實現(xiàn)了與 DOM中類似的兩個方法:attachEvent()和 detachEvent()。這兩個方法接受相同 的兩個參數(shù):事件處理程序名稱與事件處理程序函數(shù)。由于 IE8 及更早版本只支持事件冒泡,所以通過 attachEvent()添加的事件處理程序都會被添加到冒泡階段。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert("Clicked");
});
**,attachEvent()的第一個參數(shù)是"onclick",而非 DOM的 addEventListener()方法中 的"click"。 **
在 IE 中使用 attachEvent()與使用 DOM0 級方法的主要區(qū)別在于事件處理程序的作用域。在使 用 DOM0級方法的情況下,事件處理程序會在其所屬元素的作用域內(nèi)運(yùn)行;在使用 attachEvent()方 法的情況下,事件處理程序會在全局作用域中運(yùn)行,因此 this 等于 window。
跨瀏覽器的事件處理程序
var EventUtil = {
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler){
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if (element.detachEvent){
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
//使用
var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
//這里省略了其他代碼
EventUtil.removeHandler(btn, "click", handler);
事件對象
DOM中的事件對象
event
| 屬性/方法 | 類型 | 讀/寫 | 說明 |
|---|---|---|---|
| bubbles | Boolean | 只讀 | 表明事件是否冒泡 |
| cancelable | Boolean | 只讀 | 表明是否可以取消事件的默認(rèn)行為 |
| currentTarget | Element | 只讀 | 其事件處理程序當(dāng)前正在處理事件的那個元素 |
| defaultPrevented | Boolean | 只讀 | 為 true 表示已經(jīng)調(diào)用了preventDefault() (DOM3級事件中新增) |
| detail | Integer | 只讀 | 與事件相關(guān)的細(xì)節(jié)信息 |
| eventPhase | Integer | 只讀 | 調(diào)用事件處理程序的階段:1表示捕獲階段,2表 示“處于目標(biāo)”,3表示冒泡階段 |
| preventDefault() | Function | 只讀 | 取消事件的默認(rèn)行為。如果cancelable是 true,則可以使用這個方法 |
| stopImmediatePropagation() | Function | 只讀 | 取消事件的進(jìn)一步捕獲或冒泡,同時阻止任何 事件處理程序被調(diào)用(DOM3級事件中新增) |
| stopPropagation() | Function | 只讀 | 取消事件的進(jìn)一步捕獲或冒泡。如果bubbles 為true,則可以使用這個方法 |
| target | Element | 只讀 | 事件的目標(biāo) |
| trusted | Boolean | 只讀 | 為true表示事件是瀏覽器生成的。為false表示事件是由開發(fā)人員通過JavaScript創(chuàng)建的 (DOM3級事件中新增) |
| type | String | 只讀 | 被觸發(fā)的事件的類型 |
| view | AbstractView | 只讀 | 與事件關(guān)聯(lián)的抽象視圖。等同于發(fā)生事件的 window對象 |
跨瀏覽器的事件對象
var EventUtil = {
addHandler: function(element, type, handler){
//省略的代碼
},
getEvent: function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler){
//省略的代碼
},
stopPropagation: function(event){
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
//使用
btn.onclick = function(event){
event = EventUtil.getEvent(event);
}
事件委托
//html結(jié)構(gòu)
<ul id="myLinks">
<li id="goSomewhere">Go somewhere</li>
<li id="doSomething">Do something</li>
<li id="sayHi">Say hi</li>
</ul>
//傳統(tǒng)添加事件
var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
EventUtil.addHandler(item1, "click", function(event){
location.;
});
EventUtil.addHandler(item2, "click", function(event){
document.title = "I changed the document's title";
});
EventUtil.addHandler(item3, "click", function(event){
alert("hi");
});
//事件委托
var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event){
event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event);
switch(target.id){
case "doSomething":
document.title = "I changed the document's title";
break;
case "goSomewhere":
location.;
break;
case "sayHi":
alert("hi");
break;
} });
在這段代碼里,我們使用事件委托只為<ul>元素添加了一個 onclick 事件處理程序。由于所有列表項都是這個元素的子節(jié)點,而且它們的事件會冒泡,所以單擊事件終會被這個函數(shù)處理。我們知道, 事件目標(biāo)是被單擊的列表項,故而可以通過檢測 id 屬性來決定采取適當(dāng)?shù)牟僮?。與前面未使用事件委托的代碼比一比,會發(fā)現(xiàn)這段代碼的事前消耗更低,因為只取得了一個 DOM元素,只添加了一個事件處理程序。雖然對用戶來說終的結(jié)果相同,但這種技術(shù)需要占用的內(nèi)存更少。所有用到按鈕的事件(多數(shù)鼠標(biāo)事件和鍵盤事件)都適合采用事件委托技術(shù)。