javascript 事件對象
在js中觸發一個事件的時候,會產生一個事件對象,也就是函數處理常式中的event,通過event我們可以訪問到所有與事件有關的資訊,如事件的類型、事件發生對象等等。需要注意的是關於event對象IE 和 非IE在支援方式不同。
DOM中的事件對象
不管是標籤內綁定事件,DOM0級還是DOM2級,事件處理常式都會傳入一個event。
按鈕1...var btn = document.getElementById(button);btn.onclick = function(event){ alert(event.type);};btn.addEventListener(click, function(event){ alert(event.type);});
單擊按鈕時,會輸出事件的類型event.type,也就是click。
event中具有的屬性和方法如下:
| 屬性/方法 |
類型 |
讀/寫 |
說明 |
| bubbles |
Boolean |
唯讀 |
事件是否冒泡 |
| cancelable |
Boolean |
唯讀 |
是否可以取消事件的預設行為 |
| currentTarget |
Element |
唯讀 |
事件處理常式當前正在處理事件的元素 |
| defaultPrevented |
Boolean |
唯讀 |
值為true時代表已經調用了preventDefault()(DOM3級事件中新增) |
| detail |
Integer |
唯讀 |
與事件相關的細節資訊 |
| eventPhase |
Integer |
唯讀 |
呼叫事件處理常式的階段:1表示捕獲階段,2表示“處於目標”,3表示冒泡階段 |
| preventDefault |
Function |
唯讀 |
取消事件的預設行為。當cancelable為true時可以使用這個方法 |
| stopImmediatePropagation |
Function |
唯讀 |
取消事件的進一步捕獲或冒泡,同時阻止任何事件處理常式被調用(DOM3級事件中新增) |
| stopPropagation |
Function |
唯讀 |
取消事件的進一步捕獲或冒泡。當bubbles為true時可以使用這個方法 |
| target |
Element |
唯讀 |
事件的目標 |
| trusted |
Boolean |
唯讀 |
為true表示瀏覽器產生,為false表示事件是由開發人員通過Javascript建立的(DOM3級事件中新增) |
| type |
String |
唯讀 |
被觸發的事件的類型 |
| view |
AbstractView |
唯讀 |
與事件關聯的抽象視圖。等同於發生事件的window對象 |
target 和 currentTarget
首先注意到event中存在target和currentTarget,前者代表事件的目標,這個目標是事件觸發的原始目標,後者代表當前事件進行到的目標(因為事件會捕獲或冒泡,所以不一定是事件的原始目標)
當事件處理常式就在目標元素上時,這兩者是一樣的。
var btn = document.getElementById(button);btn.onclick = function(event){ console.log(this === event.target); //true console.log(this === event.currentTarget); //true}
但是如果btn在一個div內,現在給btn的父節點添加監聽:
按鈕
var btnWrap= document.getElementById(btnWrap);btnWrap.onclick = function(event){ console.log(event.target=== btn); //true console.log(event.currentTarget=== btnWrap); //true}
點擊按鈕時,事件從按鈕傳到btnWrap,此時在btnWrap的事件處理常式中,事件的原始發生者target是btn,但是當前處理事件的是btnWrap。
cancelable 和 preventDefault()
想阻止特時間點事件的預設行為可以使用preventDefault方法,比較典型的是a標籤的預設行為是開啟其href屬性指定的url,如果想阻止這個行為,在onclick事件處理常式中調用preventDefault方法即可。
var link = document.getElementById(myLink);link.onclick = function(event){ event.preventDefault();}
需要注意的是只有cancelable為true的事件才能使用preventDefault方法取消預設行為。
stopPropagation()
stopPropagation可以立即停止事件在DOM中的傳播,比如在某一個Div中有一些小按鈕,根據事件冒泡,單擊小按鈕時同樣會觸發div的事件,為了防止這種情況可以使用stopPropagation()。
var btn = document.getElementById(button);btn.onclick = function(event){ event.stopPropagation();}var btnWrap= document.getElementById(btnWrap);btnWrap.onclick = function(event){ console.log(事件到達!); //不會輸出}
IE中的事件對象
與DOM中的事件對象不同,IE中的event對象具有不同的屬性,而且訪問的方式不同。
在IE中通過DOM0級事件綁定的事件,event並不是一個局部變數,而是作為window的一個屬性存在。
var btn = document.getElementById(button);btn.onclick = function(event){ alert(event.type); //出錯!}btn.onclick = function(){ alert(window.event.type); //輸出click}
但是如果事件是通過attachEvent添加或者是直接綁定的,則和DOM中一樣是一個局部變數,可以直接存取。
按鈕1...var btn = document.getElementById(button);btn.attachEvent(onclick, function(event){ alert(event.type); // 輸出'click'});
與DOM中一樣,IE中的event同樣具有一些事件相關的屬性,如下
| 屬性/方法 |
類型 |
讀/寫 |
說明 |
| cancelBubble |
Boolean |
讀/寫 |
預設值為false,但將其設定成true則可以取消事件冒泡(與DOM中stopPropagation()方法作用相同) |
| returnValue |
Boolean |
讀/寫 |
預設值為true,但將其設定成false則可以取消事件的預設行為(與DOM中preventDefault()方法作用相同) |
| srcElement |
Element |
唯讀 |
事件的目標(與DOM中的target屬性相同) |
| type |
String |
唯讀 |
被觸發的事件的類型 |
srcElement
上一篇部落格提到,在IE的attachEvent方法類,this並不是指向當前觸發事件的元素,而是全域變數window,所以在事件處理常式內部最好還是使用event.srcElement比較保險。
var btn = document.getElementById(button);btn.onclick = function(){ alert(window.event.srcElement === this); //true}btn.attachEvent(onclick, function(){ alert(window.event.srcElement === this); //false}
returnValue
returnValue作用和DOM中的preventDefault()方法類似,將其賦值為false可以阻止事件預設行為。
btn.attachEvent(onclick, function(){ window.event.returnValue = false;}
cancelBubble
cancelBubble作用和DOM中stopPropagation()方法類似,將其賦值為true可以阻止事件進一步冒泡。
btn.attachEvent(onclick, function(){ window.event.cancelBubble = true;}
編寫跨瀏覽器的事件對象
和上篇部落格中提到的事件處理常式類似,事件對象同樣需要為跨瀏覽器進行處理,根據DOM和IE的不同實現提供統一的方法。
var EventUtil = { //添加事件,見上篇部落格 addHandler: function(element, type, handler){}, //移除事件,見上篇部落格 removeHandler: 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; } } //阻止事件捕獲或冒泡(在IE中只存在冒泡) stopPropagation: function(event){ if(event.stopPropagation){ event.propagation(); }else{ event.cancelBubble = true; } }}