標籤:
事件對象
在觸發DOM上的某個事件時,會產生一個事件對象event,這個對象中包含著所有與事件有關的資訊。包括導致事件的元素、事件的類型,以及其他與特定事件相關的資訊。例如,滑鼠操作導致的事件對象中,會包含滑鼠位置的資訊,而鍵盤操作導致的事件對象中,會包含與按下的鍵有關的資訊。所有瀏覽器對象都支援event對象,但支援方式不同。
DOM中的事件對象
相容DOM的瀏覽器會將一個event對象傳入到事件處理常式中。無論指定事件處理常式時使用什麼方法(DOM0級或DOM2級),都會傳入event對象。來看下面的例子
var btn = document.getElementById("myBtn");btn.onclick = function(event){ alert(event.type); //"click"};btn.addEventListener("click",function(event){ alert(event.type); //"click"},false);
這兩個例子中的兩個事件處理常式都會彈出一個警告框,顯示由event.type屬性工作表示的事件類型。這個屬性始終都會包含被觸發的事件類型。
在通過HTML特性指定事件處理常式時,變數event中儲存著event對象。請看下面的例子:
<input type="button" value="Click me" onclick="alert(event.type)"/>
Event對象包含與建立它的特定事件有關的屬性和方法。觸發的事件類型不一樣,可用的屬性和方法也不一樣。不過,所有事件都會有下表列出的成員。
屬性/方法 |
類型 |
讀/寫 |
說明 |
bubbles |
Boolean |
唯讀 |
表明事件是否冒泡 |
cancelable |
Boolean |
唯讀 |
表明是否可以取消事件的預設行為 |
currentTarget |
Element |
唯讀 |
其事件處理常式當前正在處理事件的那個元素 |
Detail |
Integer |
唯讀 |
與事件相關的細節資訊 |
eventPhase |
Integer |
唯讀 |
呼叫事件處理常式的階段:1表示捕獲階段,2表示“處於目標”,3表示冒泡階段 |
preventDefault() |
Function |
唯讀 |
取消事件的預設行為。如果cancelable是true,則可以使用這個方法 |
stopPropagation() |
Fucntion |
唯讀 |
取消事件的進一步捕獲或冒泡。如果bubbles為true,則可以使用這個方法 |
target |
Element |
唯讀 |
事件的目標 |
type |
String |
唯讀 |
被觸發的事件的類型 |
View |
AbstractView |
唯讀 |
與事件關聯的抽象視圖。等同於發生事件的window對象 |
在事件處理常式內部,對象this始終等於currentTarget的值,而target則只包含事件的實際目標。如果直接將事件處理常式制定為了目標元素,則this、currentTarget和target包含相同的值。來看下面的例子:
var btn = document.getElementById("myBtn");btn.onclick = function(event){ alert(event.currentTarget === this); // true alert(event.target === this) //true};
這個例子檢測了currentTarget和target與this的值。由於click事件的目標就是按鈕,因此這三個值是相等的。如果事件處理常式存在於按鈕的父節點中,那麼這些值是不同的。
document.body.onclick = function(event){ alert(event.currentTarget === document.body); //true alert(this === document.body); //true alert(event.target === document.getElementById("myBtn")) //true};
當單擊這個例子中的按鈕時,this和currentTarget都等於document.body,因為事件處理常式是註冊到這個元素上的。然而,target元素卻等於按鈕元素,因為它是click事件真正的目標。由於按鈕上沒有註冊事件處理常式,結果click事件就冒泡到了document.body,在那裡事件才得到了處理。
要阻止特定事件的預設行為,可以使用preventDefault()方法。例如連結的預設行為就是在被單擊時會導航到其href特性指定的URL。如果想要阻止連結導航這一預設行為,那麼通過連結的onclick事件處理常式就可以取消它,如下面的例子
var link = document.getElementById("myLink");link.onclick = function(event){ event.preventDefault();};
只有cancelable屬性設定為true的事件,才可以使用preventDefault()來取消其預設行為。另外stopPropagation()方法用於立即停止事件在DOM層次中的傳播,即取消進一步的事件捕獲或冒泡。例如,直接添加到一個按鈕的事件處理常式可以調用stopPropagation(),從而避免觸發註冊在document.body上面的事件處理常式,如下面的例子所示:
var btn = document.getElementById("myBtn");btn.onclick = function(event){ alert("Clicked"); event.stopPropagation();};document.body.onclick = function(event){ alert("Body clicked");};
對這個例子而言,如果不調用stopPropagation(),就會在單擊按鈕時出現兩個警告框。可是由於click事件根本不會傳播到document.body,因此就不會觸發註冊在這個元素上的onclick事件處理常式。
事件對象的eventPhase屬性,可以用來確定事件當前正位於事件流的哪個階段。如果是在捕獲階段呼叫事件處理常式eventPhase等於1,如果事件處理常式處於目標對象上,則eventPhase等於2,如果是在冒泡階段調用的事件處理常式,eventPhase等於3。需要注意的是,儘管“處於目標”發生在冒泡階段,但eventPhase仍然一直等於2。來看例子:
var btn = document.getElementById("myBtn");btn.onclick = function(event){ alert(event.eventPhase); //2};document.body.addEventListener("click",function(event){ alert(event.eventPhase); //1},true);document.body.onclick = function(event){ alert(event.eventPhase); //3};
當單擊這個例子中的按鈕時,首先執行的事件處理常式是在捕獲階段觸發的添加到docuemnt.body中的那一個,結果會彈出一個警告框顯示為eventPhase的1。接著,會觸發在按鈕上註冊的事件處理常式,此時的eventPhase值為2,最後一個被觸發的事件處理常式,是在冒泡階段執行的添加到document.body上的那一個,顯示eventPhase的值為3。而當eventPhase等於2時,this、target和currentTarget始終都是相等的。
只有在事件處理常式執行期間,event對象才會存在,一旦事件處理常式執行完成後,event對象就會被銷毀。
IE中的事件對象
與訪問DOM中的event對象不同,要訪問IE中的event對象有幾種不同的方式,取決於指定事件處理常式的方法。在使用DOM0級方法添加處理常式時,event對象作為window對象的一個屬性存在。來看下面的例子:
var btn = document.getElementById("myBtn");btn.onclick = function(){ var event = window.event; alert(event.type); //"click"};
可是如果事件處理常式是使用attachEvent()添加的,那麼就會有一個event對象作為參數被傳入事件處理常式函數中,例如:
var btn = document.getElementById("myBtn");btn.attachEvent("onclick",function(event){ alert(event.type); //"click"});
在像這樣使用attachEvent()的情況下,也可以通過window對象來訪問event對象,就像使用DOM0級方法時一樣。不過方便起見,同一個對象也會作為參數傳遞。
如果是通過HTML特性指定的事件處理常式,那麼還可以通過一個名叫event的變數來訪問event對象。
<input type="button" value="Click me" onclick="alert(event.type)"/>
IE的event對象同樣也包含與建立它的事件相關的屬性和方法。其中很多屬性和方法都有對應的或者相關的DOM屬性和方法,但所有事件對象都會包含下表所列的屬性和方法。
屬性/方法 |
類型 |
讀/寫 |
說明 |
cancelBubbles |
Boolean |
讀/寫 |
預設值為false,但將其設定為true就可以取消事件冒泡(與DOM中的stopPropagation()方法的作用相同) |
returnValue |
Boolean |
讀/寫 |
預設值為true,但將其設定為false就可以取消事件的預設行為(與DOM中的preventDefault()方法的作用相同) |
srcElement |
Element |
唯讀 |
事件的目標(與DOM中的target屬性相同) |
type |
String |
唯讀 |
被觸發的事件的類型 |
因為事件處理常式的範圍是根據指定它的方式來確定的,所以不能認為this會始終等於事件目標。故而,最好還是使用event.srcElement比較保險。例如:
var btn = document.getElementById("myBtn");btn.onclick = function(){ alert(window.event.srcElement === this); //true};btn.attachEvent("onclick",function(event){ alert(event.srcElement === this); //false});
第一個事件處理常式中(使用DOM0級方法指定),srcElement屬性等於this,但在第二個事件處理常式中this等於window,這兩者的值不同。
跨瀏覽器的事件對象
雖然DOM和IE的event對象不同,但基於它們之間的相似性依舊可以拿出跨瀏覽器的方案來。IE中的event對象的全部資訊和方法DOM對象中都有,只不過實現方式不一樣。不過,這種對應關係讓實現兩種事件模型之間的映射非常容易。
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; } }, 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){ if(element.removeEventListner){ element.removeEventListner(type,handler,false); } else if(element.detachEvent){ element.detachEvent("on"+type,handler); } else { element["on"+type] = null; } }, stopPropagation:function(event){ if(event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }};
js事件對象--DOM中的事件對象/IE中的事件對象/跨瀏覽器的事件對象