JavaScript事件的一個重要的方面是它們擁有一些相對一致的特點,可以給開發提供強大的功能;
最方便和強大的就是事件對象,它們可以幫你處理鼠標事件和鍵盤敲擊方面的情況;
此外還可以修改一般事件的捕獲/冒泡流的函數;
一 事件對象
// 事件處理函數的一個標准特性是:以某些方式訪問的事件對象包含有關於當前事件的上下文信息;
// 事件處理由三部分組成:對象.事件處理函數=函數;
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;得到一個隱藏參數;
}
// PS:通過上面兩組函數,我們發現,通過事件綁定的執行函數是可以得到一個隱藏參數的;
// 說明,浏覽器會自動分配一個參數,這個參數其實就是event對象;
input.onclick = function(){
alert(arguments[0]); // MouseEvent,鼠標事件對象;
}
// 上面這種做法比較麻煩,那麼比較簡單的做法是,直接通過接收參數來得到即可;
input.onclick = function(evt){ // 接受event對象,
alert(evt); // MouseEvent,鼠標事件對象;
}
// 直接接收event對象,是W3C的做法,IE不支持,IE自己定義了一個event對象,直接在window.event獲取即可;
input.onclick = function(evt){
var e = evt || window.event;
alert(e); // 實現跨浏覽器兼容獲取event對象;
}
// 通過事件對象可以獲取到鼠標按鈕信息和屏幕坐標獲取等;
二 鼠標事件
// 鼠標事件是Web上面最常用的一類事件,畢竟鼠標還是最主要的定位設備;
1.鼠標按鈕
// 只有在主鼠標按鈕被單擊時(一般是鼠標左鍵)才會觸發click事件,因此檢測按鈕的信息並不是必要的;
// 但對於mousedown和mouseup事件來說,則在其event對象存在一個button屬性,表示按下或釋放按鈕;
非IE(W3C)中的button屬性
值 說明
0 表示主鼠標按鈕(一般是鼠標左鍵);
1 表示中間的鼠標按鈕(鼠標滾輪按鈕);
2 表示次鼠標按鈕(一般是鼠標右鍵);
IE中的button屬性
1 表示主鼠標按鈕(一般是鼠標左鍵);
2 表示次鼠標按鈕(一般是鼠標右鍵);
4 表示按下了中間的鼠標按鈕;
// 鼠標按鈕兼容;
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('按下了右鍵!');
}
}
2.可視區及屏幕坐標
// 事件對象提供了兩組來獲取浏覽器坐標的屬性:
// 一組是頁面可視區坐標;
// 一組是屏幕坐標;
坐標屬性
屬性 說明
clientX 可視區X坐標,距離左邊框的距離;
clientY 可視區Y坐標,距離上邊框的距離;
screenX 屏幕區X坐標,距離左屏幕的距離;
screenY 屏幕區Y坐標,距離上屏幕的距離;
pageX 頁面中X坐標,距離整個頁面左邊框的距離;
pageY 頁面中Y坐標,距離整個頁面上邊框的距離;
// 判斷鼠標點擊位置函數;
document.onclick = function(evt){
var e = evt || window.event;
alert(e.clientX+','+e.clientY);
alert(e.screenX+','+e.screenY);
alert(e.pageX+','+e.pageY);
}
// PS:在頁面沒有滾動的情況下,pageX和pageY的值與clientX和clientY的值相等;
// IE8以下不支持事件對象上的頁面坐標,不過使用客戶區坐標和滾動信息可以計算出來;
// 這時候需要用到document.body(混雜模式)或document.documentElement(標准模式)中的scrollTop和scrollLeft屬性;
// pageX和pageY兼容函數;
var div = document.getElementById('myDiv');
addEventListener(div,'click',function(evt){
var evt = event || window.event;
var pageX = evt.pageX,
pageY = evt.pageY;
if(pageX === undefined){
pageX = evt.clientX+(docuemnt.body.scrollLeft || document.documentElement.scrollLeft);
}
if(pageY === undefined){
pageY = evt.clientY+(document.body.scrollTop || document.documentElement.srollTop);
}
alert(pageX+pageY);
});
3.修改鍵
// 有時,我們需要通過鍵盤上的某些鍵來配合鼠標來觸發一些特殊的事件;
// 這些鍵為:Shift/Ctrl/Alt和Meat(Window中是Windows鍵,蘋果機中是Cmd鍵);
// 它們經常被用來修改鼠標事件和行為,所以叫修改鍵;
修改鍵屬性
屬性 說明
shiftKey 判斷是否按下了Shift鍵;
ctrlKey 判斷是否按下了ctrlKey鍵;
altKey 判斷是否按下了alt鍵;
metaKey 判斷是否按下了windows鍵,IE不支持;
// 判斷按鍵函數;
function getKey(evt){
var e = evt || window.event;
var keys = [];
if(e.shiftKey) keys.push('shift'); // 判斷是否同時按下了shift鍵;
if(e.ctrlKey) keys.push('ctrl');
if(e.altKey) keys.push('alt');
return keys;
}
document.onclick = function(evt){
alert(getKey(evt)); // 得到一個數組,可能包含shift/ctrl/alt的值;
}
三 鍵盤事件
用戶在使用鍵盤時會觸發鍵盤事件;
"DOM2級事件"最初規定了鍵盤事件,後來又刪除了相應的內容;
最終還是使用最初的鍵盤事件,不過IE9已經率先支持"DOM3"級鍵盤事件;
1.鍵碼
// 在發生keydown和keyup事件時,event對象的keyCode屬性中會包含一個代碼,與鍵盤上一個特定的鍵對應;
// 對數字字母字符集,keyCode屬性的值與ASCII碼中對應小寫字母或數字的編碼相同;字母中大小寫不影響;
document.onkeydown = function(evt){
alert(evt.keyCode);
}
2.字符編碼
// Firefox/Chrome/Safari的event對象都支持一個charCode屬性;
// 這個屬性只有在發生keypress事件時才會包含值,而這個值是按下的那個鍵所代表字符的ASII編碼;(也包含除數字和字母以外的按鍵);
// 此時的keyCode通常等於0或者也可能等於所按鍵的編碼;
// IE和Opear則是在keyCode中保存字符的ASCII編碼;
function getCharCode(evt){
var e = evt || window.event;
if(typeof e.charCode == 'number'){
return e.charCode;
}else{
return e.keyCode;
}
}
document.onkeypress = function(evt){
alert(getCharCode(evt));
}
// PS:可以使用String.fromCharCode()將ASCII編碼轉換成實際的字符;
四 W3C與IE
// 在標准的DOM事件中,event對象包含與創建它的特定事件有關的屬性和方法;
// 觸發的事件類型不一樣,可用的屬性和方法也不一樣;
W3C中event對象的屬性和方法
屬性/方法 類型 讀/寫 說明
bubbles Boolean 只讀 表明事件是否冒泡;
cancelable Boolean 只讀 表明是否可以取消事件的默認行為;
currentTarget Element 只讀 其事件處理程序當前正在處理事件的那個元素;
detail Integer 只讀 與事件相關的細節信息;(一般用於滾輪信息的值);
eventPhase Integer 只讀 調用事件處理程序的階段:1表示捕獲階段,2表示處理目標,3表示冒泡階段;
preventDefault() Function 只讀 取消事件的默認行為;如果cancelable的值是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 只讀 被觸發的事件類型;
// 兼容target和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);
}
五 事件流
事件流是描述的從頁面接收事件的順序,當幾個都具有事件的元素層疊在一起的時候,那麼點擊其中一個元素;
並不是只有當前被點擊的元素會觸發事件,而是層疊在點擊范圍的所有元素都會觸發事件;
事件流包含兩種模式:冒泡和捕獲;
1.事件冒泡
是從裡往外逐個觸發;
2.事件捕獲
是從外往裡逐個觸發;
// 現代浏覽器都是冒泡類型;而捕獲模式是早期的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');
}
// PS:點擊input會逐級冒泡到document;
// 阻止事件冒泡兼容函數
function stopPro(evt){
var e = evt || window.event;
// 如果存在cancelBubble,則是IE浏覽器,將其值設為true就可以阻止事件冒泡;
// 否則執行W3C中的阻止事件冒泡方法stopPropagation();
window.event ? e.cancelBubble = true : e.stopPropagation();
}