說(shuō)明:本文為《JavaScript高級(jí)程序設(shè)計(jì)》第9章學(xué)習(xí)筆記。
一.今天的事件
事件是DOM的一部分,在DOM Level1中未定義任何事件,在Level中定義了一小部分子集,完整的事件是在Level3中規(guī)定的,該標(biāo)準(zhǔn)在2004年最終定案。
Mozilla的事件模式與DOM標(biāo)準(zhǔn)最為接近,IE成為唯一一個(gè)對(duì)DOM事件模式缺乏良好支持的瀏覽器。
二.事件流
事件流意味著在頁(yè)面上可有不僅一個(gè),甚至多個(gè)元素響應(yīng)同一個(gè)事件。
1. 冒泡型事件
IE上的解決方案的綽號(hào)為冒泡的技術(shù)。冒泡型事件的基本思想是,時(shí)間按照最特定的目標(biāo)到最不特定的事件目標(biāo)的順序觸發(fā)。
IE6.0中,<html/>元素也可接收冒泡的時(shí)間。
2. 捕獲型事件
Netscape Navigator4.0使用了捕獲型事件的解決方案。事件從最不確定的對(duì)象(document對(duì)象)開始觸發(fā),然后到最精確。
3.DOM事件流
DOM同時(shí)支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流會(huì)觸發(fā)DOM中的所有對(duì)象,從document對(duì)象開始,也在document對(duì)象結(jié)束。
DOM事件模型的最獨(dú)特的性質(zhì)是,文本節(jié)點(diǎn)也觸發(fā)事件(在IE中不會(huì))。
三.時(shí)間處理函數(shù)/監(jiān)聽函數(shù)
事件是用戶或?yàn)g覽器自身進(jìn)行的特定行為。這些事件都有自己的名字,如click、load等。用于響應(yīng)某個(gè)事件而調(diào)用的函數(shù)稱為事件處理函數(shù)。
如果是JavaScript中分配的事件處理函數(shù),則需要首先獲得要處理對(duì)象的引用,然后將函數(shù)賦值給事件處理函數(shù)屬性,eg1.
var oDiv = document.getElementById(“div1”);

oDiv.onclick = function()
{
alert(“I was clicked.”);
}
用這個(gè)分配方法,事件處理函數(shù)必須小寫,才能正確響應(yīng)事件。
Eg2. <div onclick=”alert(‘I was clicked.’)”></div>
在例二中,事件處理函數(shù)的大小寫可以任意
1. IE
在IE中,每個(gè)元素和window對(duì)象都有兩個(gè)方法:attachEvent()和detachEvent()。attachEvent()用來(lái)給一個(gè)事件附加事件處理函數(shù)。而detachEvent()用來(lái)將事件處理函數(shù)分離出來(lái)。Eg.

var fnClick = function()
{
alert(“Clicked!”);
}
var oDiv = document.getElementById(“div1”);
oDiv.attachEvent(“onclick”, fnClick);
oDiv.detachEvent(“onclick”, fnClick);
2. DOM
DOM方法addEventListener()和removeEventListener()用來(lái)分配和移除事件處理函數(shù)。與IE不同,這些方法需要三個(gè)參數(shù):事件名稱、要分配的函數(shù)和處理函數(shù)用于冒泡階段(為false時(shí))還是捕獲階段(為true時(shí))。Eg.
oDiv. addEventListener (“onclick”, fnClick, false);
oDiv.removeEventListener (“onclick”, fnClick, false);
如果使用傳統(tǒng)方法直接給事件處理函數(shù)屬性賦值,事件處理函數(shù)將被添加到事件的冒泡階段,eg.
oDiv.onclick = fnClick;
oDiv.removeEventListener (“onclick”, fnClick, false);
四. 事件對(duì)象
事件對(duì)象只在發(fā)生事件時(shí)才被創(chuàng)建,且只有事件處理函數(shù)才能訪問(wèn)。所有事件處理函數(shù)執(zhí)行完畢后,事件對(duì)象就被銷毀。
1. 定位
在IE中,事件對(duì)象是window對(duì)象的一個(gè)屬性event,也就是說(shuō),事件處理函數(shù)必須這樣訪問(wèn)事件對(duì)象:
oDiv.onclick = function() {
var oEvent = window.event;
}
Event對(duì)象只能在事件發(fā)生時(shí)訪問(wèn)。所有的事件處理函數(shù)執(zhí)行完畢后,事件對(duì)象就被銷毀。
2. 屬性/方法
見頁(yè)面233-235頁(yè),在此不詳述。
3. 相似性
1) 獲取事件類型
下面代碼可在任何瀏覽器中獲取事件的類型:
var sType = oEvent.type;
它返回“click”或“mouseover”之類的值。Eg.

function handleEvent(oEvent)
{

if (oEvent.type == “click”)
{
alert(“Clicked!”);

} else if (oEvent.type == “mouseover”)
{
alert(“mouse over!”);
}
}
oDiv.onclick = handleEvent;
oDiv.onmouseover = handleEvent;
2) 獲取按鍵代碼
Eg. var iKeyCode = oEvent.keyCode;
例如,Enter鍵的keyCode為13,空格鍵的keyCode為32,回退鍵為8.
3) 檢測(cè)Shift、Alt和Ctrl鍵
Eg. var bShift = oEvent.shiftKey;
var bAlt = oEvent.altKey;
var bCtrl = oEvent.ctrlKey;
4) 獲取客戶端坐標(biāo)
Eg. var iClientX = oEvent.clientX;
var iClientY = oEvent.clientY;
5) 獲取屏幕坐標(biāo)
可用screenX和screenY屬性來(lái)獲取鼠標(biāo)指針在計(jì)算機(jī)屏幕中的位置
var iScreenX = oEvent.screenX;
var iScreenY = oEvent.screenY;
4.區(qū)別
1)獲取目標(biāo)
在IE中:var oTarget = oEvent.srcElement;
在DOM兼容的瀏覽器中:var oTarger = oEvent.target;
2)獲取字符代碼
在IE中:var iCharCode = oEvent.keyCode;
在DOM兼容的瀏覽器中:var iCharCode = oEvent.charCode;
3)阻止某個(gè)事件的默認(rèn)行為
在IE中:oEvent.returnValue = false;
在DOM兼容的瀏覽器中:oEvent.preventDefault();
4)阻止事件復(fù)制(冒泡)
在IE中:oEvent.cancelBubble = true;
在mozilla中:oEvent.stopPropagation ();
五.事件的類型
DOM標(biāo)準(zhǔn)定義了以下幾種事件:
鼠標(biāo)事件
鍵盤事件
HTML事件:窗口發(fā)生變動(dòng)或者發(fā)生特定的客戶端-服務(wù)端交互時(shí)觸發(fā);
突變事件:底層的DOM結(jié)構(gòu)發(fā)生改變時(shí)觸發(fā)。
1. 鼠標(biāo)事件
Eg. click、dbclick、mousedown、mouseout、mouseover、mouseup、mouseover。
1) 屬性
Eg. 坐標(biāo)屬性(eg。clientX和clientY等)、type屬性、target或srcElement屬性、shiftKey、ctrlKey、altKey、metaKey(DOM)屬性、button屬性(只在mousedown、mouseover、mouseout、mouseover和mouseup事件中)。
2) 順序
在同一個(gè)目標(biāo)上要按順序發(fā)生以下事件: mousedown->mouseup->click->mousedown->mouseup->click->dbclick。
2. 鍵盤事件
鍵盤事件有:keydown、keypress和keyup。
1) 事件的屬性
對(duì)某個(gè)鍵盤事件,會(huì)填入如下的事件屬性: keyCode、charCode(僅DOM)、target(DOM)或者srcElement(IE)、shiftKey、ctrlKey、altKey、metaKey(DOM)屬性。
2) 順序
按下一個(gè)字符鍵,發(fā)生事件順序?yàn)?/span>: keydown->keypress->keyup;
按下一個(gè)非字符鍵,發(fā)生事件順序?yàn)?/span>:keydown->keyup。
3. HTML事件
HTML事件有: load、unload、abort、error、select、change、submit、reset、resize、scroll、focus、blur事件。
1) load和unload事件
eg. window.onload = function() {
alert(“loaded!”);
}
2) resize事件
resize事件用來(lái)判斷何時(shí)動(dòng)態(tài)的改變某些元素。Eg.
<body onresize=”alert(‘Resizing’)”>
最大化或最小化窗口時(shí),也會(huì)觸發(fā)resize事件。
3) Scroll事件
Eg. <body onscroll=”alert(‘Scroll)”>
4.變化事件
變化事件包括如下內(nèi)容:
DOMSubtreeModified——當(dāng)文檔或者元素的子樹因?yàn)樘砑踊騽h除節(jié)點(diǎn)而改變時(shí)觸發(fā);
DOMNodeInserted——當(dāng)一個(gè)節(jié)點(diǎn)作為另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)插入時(shí)觸發(fā);
DOMNodeRemoved——當(dāng)一個(gè)節(jié)點(diǎn)作為另一個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)刪除時(shí)觸發(fā);
DOMNodeRemovedFromDocument——當(dāng)一個(gè)節(jié)點(diǎn)從文檔中刪除時(shí)觸發(fā);
DOMNodeInsertedIntoDocument——當(dāng)一個(gè)節(jié)點(diǎn)插入到文檔中時(shí)觸發(fā)。
這些事件的目的是,提供一個(gè)獨(dú)立于語(yǔ)言的事件范圍,使其可使用在所有基于XML的語(yǔ)言中。
六.跨平臺(tái)的事件
1. EventUtil對(duì)象
var EventUtil = new Object;
2. 添加/刪除事件處理函數(shù)

EventUtil.addEventHandler = function()
{

if (oTarget.addEventListener)
{ //對(duì)DOM兼容的瀏覽器
oTarget.addEventListener(sEventType, fnHandler, false);

} else if (oTarget.attachEvent)
{ //對(duì)IE
oTarget.attachEvent("on" + sEventType, fnHandler);

} else
{
oTarget["on" + sEventType] = fnHandler;
}
}


EventUtil.removeHandler = function(oTarget, sEventType, fnHandler)
{

if (oTarget.removeEventListener)
{ //對(duì)DOM兼容的瀏覽器
oTarget.removeEventListener(sEventType, fnHandler, false);

} else if (oTarget.detachEvent)
{ //對(duì)IE
oTarget.detachEvent("on" + sEventType, fnHandler);

} else
{
oTarget["on" + sEventType] = null;
}
}
3. 格式化event對(duì)象
一種對(duì)付IE和DOM中的event對(duì)象之間區(qū)別的最佳手段是,調(diào)整它們使之盡可能地表現(xiàn)相似,因?yàn)楦嗟臑g覽器使用的是DOM的事件類型,所以將IE的事件模型調(diào)整為接近于DOM事件模型就可以了。
根據(jù)DOM屬性/方法與IE屬性/方法的不同,最后可得出如下的格式化event對(duì)象函數(shù),如下所示:

EventUtil.formatEvent = function(oEvent)
{

if (isIE && isWin)
{
oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
oEvent.eventPhase = 2;
oEvent.isChar = (oEvent.charCode > 0);
oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
oEvent.pageY = oEvent.clientY + document.body.scrollTop;

oEvent.preventDefault = function()
{
this.returnValue = false;
};


if (oEvent.type == "mouseout")
{
oEvent.relatedTarget = oEvent.toElement;

} else if (oEvent.type == "mouseover")
{
oEvent.relatedTarget = oEvent.fromElement;
}

oEvent.stopPropagation = function()
{
this.cancelBubble = true;
};
oEvent.target = oEvent.srcElement;
oEvent.time = (new Date()).getTime();
}
return oEvent;
}
4. 獲取事件對(duì)象
IE和DOM使用不同的方法來(lái)獲取event對(duì)象。在IE中,event對(duì)象是與window對(duì)象相關(guān)的,而在DOM中,它獨(dú)立于任何其他對(duì)象,并且是作為參數(shù)傳遞的。下面我們編寫一個(gè)通用的獲取event對(duì)象的函數(shù),代碼如下:

EventUtil.getEvent = function()
{

if (window.event)
{
return this.formatEvent(window.event);

} else
{
return EventUtil.getEvent.caller.arguments[0];
}
}
調(diào)用舉例如下:

oDiv.onclick = function()
{
var oEvent = EventUtil.getEvent();
}
七. 小結(jié)
本章詳細(xì)介紹了JavaScript中事件、事件流的概念,詳細(xì)研究了event對(duì)象,最后一節(jié)還創(chuàng)建了一個(gè)跨瀏覽器事件庫(kù),可使用同一套方法來(lái)訪問(wèn)事件對(duì)象,添加/刪除事件處理函數(shù),而無(wú)需考慮瀏覽器檢測(cè)的問(wèn)題。
posted on 2007-08-27 09:17
阿蜜果 閱讀(3778)
評(píng)論(9) 編輯 收藏 所屬分類:
Javascript