二十一、事件對象
二十一、事件對象
JavaScript事件的一個重要方面是它們擁有一些相對一致的特點,可以給你的開發提供更多的強大功能。最方便和強大的就是事件對象,他們可以幫你處理鼠標事件和鍵盤敲擊方面的情況,此外還可以修改一般事件的捕獲/冒泡流的函數。
1.事件對象
事件處理函數的一個標準特性是,以某些方式訪問的事件對象包含有關於當前事件的上下文信息。
事件處理三部分組成:對象.事件處理函數=函數。例如:單擊文檔任意處。
document.onclick = function () {
alert(‘Lee‘);
};
PS:以上程序的名詞解釋:click表示一個事件類型,單擊。onclick表示一個事件處理函數或綁定對象的屬性(或者叫事件監聽器、偵聽器)。document表示一個綁定的對象,用於觸發某個元素區域。function()匿名函數是被執行的函數,用於觸發後執行。
除了用匿名函數的方法作為被執行的函數,也可以設置成獨立的函數。
document.onclick = box; //直接賦值函數名即可,無須括號
function box() {
alert(‘Lee‘);
}
this關鍵字和上下文
在面向對象那章我們了解到:在一個對象裏,由於作用域的關系,this代表著離它最近對象。
var input = document.getElementsByTagName(‘input‘)[0];
input.onclick = function () {
alert(this.value); //HTMLInputElement,this表示input對象
};
從上面的拆分,我們並沒有發現本章的重點:事件對象。那麽事件對象是什麽?它在哪裏呢?當觸發某個事件時,會產生一個事件對象,這個對象包含著所有與事件有關的信息。包括導致事件的元素、事件的類型、以及其它與特定事件相關的信息。
事件對象,我們一般稱作為event對象,這個對象是瀏覽器通過函數把這個對象作為參數傳遞過來的。那麽首先,我們就必須驗證一下,在執行函數中沒有傳遞參數,是否可以得到隱藏的參數。
function box() { //普通空參函數
alert(arguments.length); //0,沒有得到任何傳遞的參數
}
input.onclick = function () { //事件綁定的執行函數
alert(arguments.length); //1,得到一個隱藏參數
};
通過上面兩組函數中,我們發現,通過事件綁定的執行函數是可以得到一個隱藏參數的。說明,瀏覽器會自動分配一個參數,這個參數其實就是event對象。
input.onclick = function () {
alert(arguments[0]); //MouseEvent,鼠標事件對象
};
上面這種做法比較累,那麽比較簡單的做法是,直接通過接收參數來得到即可。
input.onclick = function (evt) { //接受event對象,名稱不一定非要event
alert(evt); //MouseEvent,鼠標事件對象
};
直接接收event對象,是W3C的做法,IE不支持,IE自己定義了一個event對象,直接在window.event獲取即可。
input.onclick = function (evt) {
var e = evt || window.event; //實現跨瀏覽器兼容獲取event對象
alert(e);
};
2.鼠標事件
鼠標事件是Web上面最常用的一類事件,畢竟鼠標還是最主要的定位設備。那麽通過事件對象可以獲取到鼠標按鈕信息和屏幕坐標獲取等。
1.鼠標按鈕
只有在主鼠標按鈕被單擊時(常規一般是鼠標左鍵)才會觸發click事件,因此檢測按鈕的信息並不是必要的。但對於mousedown和mouseup事件來說,則在其event對象存在一個button屬性,表示按下或釋放按鈕。
非IE(W3C)中的button屬性
值 |
說明 |
0 |
表示主鼠標按鈕(常規一般是鼠標左鍵) |
1 |
表示中間的鼠標按鈕(鼠標滾輪按鈕) |
2 |
表示次鼠標按鈕(常規一般是鼠標右鍵) |
IE中的button屬性
值 |
說明 |
0 |
表示沒有按下按鈕 |
1 |
表示主鼠標按鈕(常規一般是鼠標左鍵) |
2 |
表示次鼠標按鈕(常規一般是鼠標右鍵) |
3 |
表示同時按下了主、次鼠標按鈕 |
4 |
表示按下了中間的鼠標按鈕 |
5 |
表示同時按下了主鼠標按鈕和中間的鼠標按鈕 |
6 |
表示同時按下了次鼠標按鈕和中間的鼠標按鈕 |
7 |
表示同時按下了三個鼠標按鈕 |
PS:在絕大部分情況下,我們最多只使用主次中三個單擊鍵,IE給出的其他組合鍵一般無法使用上。所以,我們只需要做上這三種兼容即可。
function getButton(evt) { //跨瀏覽器左中右鍵單擊相應
var e = evt || window.event;
if (evt) { //Chrome瀏覽器支持W3C和IE
return e.button; //要註意判斷順序
} else if (window.event) {
switch(e.button) {
case 1 :
return 0;
case 4 :
return 1;
case 2 :
return 2;
}
}
}
document.onmouseup = function (evt) { //調用
if (getButton(evt) == 0) {
alert(‘按下了左鍵!‘);
} else if (getButton(evt) == 1) {
alert(‘按下了中鍵!‘);
} else if (getButton(evt) == 2) {
alert(‘按下了右鍵!‘ );
}
};
1.可視區及屏幕坐標
事件對象提供了兩組來獲取瀏覽器坐標的屬性,一組是頁面可視區左邊,另一組是屏幕坐標。
坐標屬性
屬性 |
說明 |
clientX |
可視區X坐標,距離左邊框的位置 |
clientY |
可視區Y坐標,距離上邊框的位置 |
screenX |
屏幕區X坐標,距離左屏幕的位置 |
screenY |
屏幕區Y坐標,距離上屏幕的位置 |
document.onclick = function (evt) {
var e = evt || window.event;
alert(e.clientX + ‘,‘ + e.clientY);
alert(e.screenX + ‘,‘ + e.screenY);
};
2.修改鍵
有時,我們需要通過鍵盤上的某些鍵來配合鼠標來觸發一些特殊的事件。這些鍵為:Shfit、Ctrl、Alt和Meat(Windows中就是Windows鍵,蘋果機中是Cmd鍵),它們經常被用來修改鼠標事件和行為,所以叫修改鍵。
修改鍵屬性
屬性 |
說明 |
shiftKey |
判斷是否按下了Shfit鍵 |
ctrlKey |
判斷是否按下了ctrlKey鍵 |
altKey |
判斷是否按下了alt鍵 |
metaKey |
判斷是否按下了windows鍵,IE不支持 |
function getKey(evt) {
var e = evt || window.event;
var keys = [];
if (e.shiftKey) keys.push(‘shift‘); //給數組添加元素
if (e.ctrlKey) keys.push(‘ctrl‘);
if (e.altKey) keys.push(‘alt‘);
return keys;
}
document.onclick = function (evt) {
alert(getKey(evt));
};
3.鍵盤事件
用戶在使用鍵盤時會觸發鍵盤事件。“DOM2級事件”最初規定了鍵盤事件,結果又刪除了相應的內容。最終還是使用最初的鍵盤事件,不過IE9已經率先支持“DOM3”級鍵盤事件。
2.鍵碼
在發生keydown和keyup事件時,event對象的keyCode屬性中會包含一個代碼,與鍵盤上一個特定的鍵對應。對數字字母字符集,keyCode屬性的值與ASCII碼中對應小寫字母或數字的編碼相同。字母中大小寫不影響。
document.onkeydown = function (evt) {
alert(evt.keyCode); //按任意鍵,得到相應的keyCode
};
不同的瀏覽器在keydown和keyup事件中,會有一些特殊的情況:
在Firefox和Opera中,分號鍵時keyCode值為59,也就是ASCII中分號的編碼;而IE和Safari返回186,即鍵盤中按鍵的鍵碼。
PS:其他一些特殊情況由於瀏覽器版本太老和市場份額太低,這裏不做補充。
3.字符編碼
Firefox、Chrome和Safari的event對象都支持一個charCode屬性,這個屬性只有在發生keypress事件時才包含值,而且這個值是按下的那個鍵所代表字符的ASCII編碼。此時的keyCode通常等於0或者也可能等於所按鍵的編碼。IE和Opera則是在keyCode中保存字符的ASCII編碼。
function getCharCode(evt) {
var e = evt || window.event;
if (typeof e.charCode == ‘number‘) {
return e.charCode;
} else {
return e.keyCode;
}
}
PS:可以使用String.fromCharCode()將ASCII編碼轉換成實際的字符。
keyCode和charCode區別如下:比如當按下“a鍵(重視是小寫的字母)時,
在Firefox中會獲得
keydown: keyCode is 65 charCode is 0
keyup: keyCode is 65 charCode is 0
keypress: keyCode is 0 charCode is 97
在IE中會獲得
keydown: keyCode is 65 charCode is undefined
keyup: keyCode is 65 charCode is undefined
keypress: keyCode is 97 charCode is undefined
而當按下shift鍵時,在Firefox中會獲得
keydown:keyCode is 16 charCode is 0
keyup: keyCode is 16 charCode is 0
在IE中會獲得
keydown:keyCode is 16 charCode is undefined
keyup: keyCode is 16 charCode is undefined
keypress:不會獲得任何的charCode值,因為按shift並沒輸入任何的字符,並且也不會觸發keypress事務
PS:在keydown事務裏面,事務包含了keyCode – 用戶按下的按鍵的物理編碼。
在keypress裏,keyCode包含了字符編碼,即默示字符的ASCII碼。如許的情勢實用於所有的瀏覽器 – 除了火狐,它在keypress事務中的keyCode返回值為0。
4.W3C與IE
在標準的DOM事件中,event對象包含與創建它的特定事件有關的屬性和方法。觸發的事件類型不一樣,可用的屬性和方法也不一樣。
W3C中event對象的屬性和方法
屬性/方法 |
類型 |
讀/寫 |
說明 |
bubbles |
Boolean |
只讀 |
表明事件是否冒泡 |
cancelable |
Boolean |
只讀 |
表明是否可以取消事件的默認行為 |
currentTarget |
Element |
只讀 |
其事件處理程序當前正在處理事件的那個元素 |
detail |
Integer |
只讀 |
與事件相關的細節信息 |
eventPhase |
Integer |
只讀 |
調用事件處理程序的階段:1表示捕獲階段,2表示“處理目標”,3表示冒泡階段 |
preventDefault() |
Function |
只讀 |
取消事件的默認行為。如果cancelabel是true,則可以使用這個方法 |
stopPropagation() |
Function |
只讀 |
取消事件的進一步捕獲或冒泡。如果bubbles為true,則可以使用這個方法 |
target |
Element |
只讀 |
事件的目標 |
type |
String |
只讀 |
被觸發的事件的類型 |
view |
AbstractView |
只讀 |
與事件關聯的抽象視圖。等同於發生事件的window對象 |
IE中event對象的屬性
屬性 |
類型 |
讀/寫 |
說明 |
cancelBubble |
Boolean |
讀/寫 |
默認值為false,但將其設置為true就可以取消事件冒泡 |
returnValue |
Boolean |
讀/寫 |
默認值為true,但將其設置為false就可以取消事件的默認行為 |
srcElement |
Element |
只讀 |
事件的目標 |
type |
String |
只讀 |
被觸發的事件類型 |
在這裏,我們只看所有瀏覽器都兼容的屬性或方法。首先第一個我們了解一下W3C中的target和IE中的srcElement,都表示事件的目標。
function getTarget(evt) {
var e = evt || window.event;
return e.target || e.srcElement; //兼容得到事件目標DOM對象
}
document.onclick = function (evt) {
var target = getTarget(evt);
alert(target);
};
事件流
事件流是描述的從頁面接受事件的順序,當幾個都具有事件的元素層疊在一起的時候,那麽你點擊其中一個元素,並不是只有當前被點擊的元素會觸發事件,而層疊在你點擊範圍的所有元素都會觸發事件。事件流包括兩種模式:冒泡和捕獲。
事件冒泡,是從裏往外逐個觸發。事件捕獲,是從外往裏逐個觸發。那麽現代的瀏覽器默認情況下都是冒泡模型,而捕獲模式則是早期的Netscape默認情況。而現在的瀏覽器要使用DOM2級模型的事件綁定機制才能手動定義事件流模式。
document.onclick = function () {
alert(‘我是document‘);
};
document.documentElement.onclick = function () {
alert(‘我是html‘);
};
document.body.onclick = function () {
alert(‘我是body‘);
};
document.getElementById(‘box‘).onclick = function () {
alert(‘我是div‘);
};
document.getElementsByTagName(‘input‘)[0].onclick = function () {
alert(‘我是input‘);
};
在阻止冒泡的過程中,W3C和IE采用的不同的方法,那麽我們必須做一下兼容。
function stopPro(evt) {
var e = evt || window.event;
window.event ? e.cancelBubble = true : e.stopPropagation();
}
二十一、事件對象