說明:本文為《JavaScript高級程序設(shè)計》第9章學(xué)習(xí)筆記。
一.今天的事件 事件是DOM的一部分,在DOM Level1中未定義任何事件,在Level中定義了一小部分子集,完整的事件是在Level3中規(guī)定的,該標(biāo)準(zhǔn)在2004年最終定案。 Mozilla的事件模式與DOM標(biāo)準(zhǔn)最為接近,IE成為唯一一個對DOM事件模式缺乏良好支持的瀏覽器。
二.事件流 事件流意味著在頁面上可有不僅一個,甚至多個元素響應(yīng)同一個事件。 1. 冒泡型事件 IE上的解決方案的綽號為冒泡的技術(shù)。冒泡型事件的基本思想是,時間按照最特定的目標(biāo)到最不特定的事件目標(biāo)的順序觸發(fā)。 IE6.0中,<html/>元素也可接收冒泡的時間。 2. 捕獲型事件 Netscape Navigator4.0使用了捕獲型事件的解決方案。事件從最不確定的對象(document對象)開始觸發(fā),然后到最精確。 3.DOM事件流 DOM同時支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流會觸發(fā)DOM中的所有對象,從document對象開始,也在document對象結(jié)束。 DOM事件模型的最獨特的性質(zhì)是,文本節(jié)點也觸發(fā)事件(在IE中不會)。
三.時間處理函數(shù)/監(jiān)聽函數(shù) 事件是用戶或瀏覽器自身進(jìn)行的特定行為。這些事件都有自己的名字,如click、load等。用于響應(yīng)某個事件而調(diào)用的函數(shù)稱為事件處理函數(shù)。 如果是JavaScript中分配的事件處理函數(shù),則需要首先獲得要處理對象的引用,然后將函數(shù)賦值給事件處理函數(shù)屬性,eg1.
var oDiv = document.getElementById(“div1”);
oDiv.onclick = function() { alert(“I was clicked.”); } 用這個分配方法,事件處理函數(shù)必須小寫,才能正確響應(yīng)事件。 Eg2. <div onclick=”alert(‘I was clicked.’)”></div> 在例二中,事件處理函數(shù)的大小寫可以任意 1. IE 在IE中,每個元素和window對象都有兩個方法:attachEvent()和detachEvent()。attachEvent()用來給一個事件附加事件處理函數(shù)。而detachEvent()用來將事件處理函數(shù)分離出來。Eg.
var fnClick = function() {
alert(“Clicked!”); } var oDiv = document.getElementById(“div1”); oDiv.attachEvent(“onclick”, fnClick); oDiv.detachEvent(“onclick”, fnClick);
2. DOM DOM方法addEventListener()和removeEventListener()用來分配和移除事件處理函數(shù)。與IE不同,這些方法需要三個參數(shù):事件名稱、要分配的函數(shù)和處理函數(shù)用于冒泡階段(為false時)還是捕獲階段(為true時)。Eg. oDiv. addEventListener (“onclick”, fnClick, false); oDiv.removeEventListener (“onclick”, fnClick, false); 如果使用傳統(tǒng)方法直接給事件處理函數(shù)屬性賦值,事件處理函數(shù)將被添加到事件的冒泡階段,eg. oDiv.onclick = fnClick; oDiv.removeEventListener (“onclick”, fnClick, false);
四. 事件對象 事件對象只在發(fā)生事件時才被創(chuàng)建,且只有事件處理函數(shù)才能訪問。所有事件處理函數(shù)執(zhí)行完畢后,事件對象就被銷毀。 1. 定位 在IE中,事件對象是window對象的一個屬性event,也就是說,事件處理函數(shù)必須這樣訪問事件對象: oDiv.onclick = function() { var oEvent = window.event; } Event對象只能在事件發(fā)生時訪問。所有的事件處理函數(shù)執(zhí)行完畢后,事件對象就被銷毀。 2. 屬性/方法 見頁面233-235頁,在此不詳述。 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) 檢測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屬性來獲取鼠標(biāo)指針在計算機(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)阻止某個事件的默認(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ā)生變動或者發(fā)生特定的客戶端-服務(wù)端交互時觸發(fā); 突變事件:底層的DOM結(jié)構(gòu)發(fā)生改變時觸發(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) 順序 在同一個目標(biāo)上要按順序發(fā)生以下事件: mousedown->mouseup->click->mousedown->mouseup->click->dbclick。 2. 鍵盤事件 鍵盤事件有:keydown、keypress和keyup。 1) 事件的屬性 對某個鍵盤事件,會填入如下的事件屬性: keyCode、charCode(僅DOM)、target(DOM)或者srcElement(IE)、shiftKey、ctrlKey、altKey、metaKey(DOM)屬性。 2) 順序 按下一個字符鍵,發(fā)生事件順序為: keydown->keypress->keyup; 按下一個非字符鍵,發(fā)生事件順序為: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事件用來判斷何時動態(tài)的改變某些元素。Eg. <body onresize=”alert(‘Resizing’)”> 最大化或最小化窗口時,也會觸發(fā)resize事件。 3) Scroll事件 Eg. <body onscroll=”alert(‘Scroll)”> 4.變化事件 變化事件包括如下內(nèi)容: DOMSubtreeModified——當(dāng)文檔或者元素的子樹因為添加或刪除節(jié)點而改變時觸發(fā); DOMNodeInserted——當(dāng)一個節(jié)點作為另一個節(jié)點的子節(jié)點插入時觸發(fā); DOMNodeRemoved——當(dāng)一個節(jié)點作為另一個節(jié)點的子節(jié)點刪除時觸發(fā); DOMNodeRemovedFromDocument——當(dāng)一個節(jié)點從文檔中刪除時觸發(fā); DOMNodeInsertedIntoDocument——當(dāng)一個節(jié)點插入到文檔中時觸發(fā)。 這些事件的目的是,提供一個獨立于語言的事件范圍,使其可使用在所有基于XML的語言中。
六.跨平臺的事件 1. EventUtil對象 var EventUtil = new Object; 2. 添加/刪除事件處理函數(shù) EventUtil.addEventHandler = function() {
if (oTarget.addEventListener) { //對DOM兼容的瀏覽器 oTarget.addEventListener(sEventType, fnHandler, false); } else if (oTarget.attachEvent) { //對IE oTarget.attachEvent("on" + sEventType, fnHandler); } else { oTarget["on" + sEventType] = fnHandler; } } EventUtil.removeHandler = function(oTarget, sEventType, fnHandler) { if (oTarget.removeEventListener) { //對DOM兼容的瀏覽器 oTarget.removeEventListener(sEventType, fnHandler, false); } else if (oTarget.detachEvent) { //對IE oTarget.detachEvent("on" + sEventType, fnHandler); } else { oTarget["on" + sEventType] = null; } } 3. 格式化event對象 一種對付IE和DOM中的event對象之間區(qū)別的最佳手段是,調(diào)整它們使之盡可能地表現(xiàn)相似,因為更多的瀏覽器使用的是DOM的事件類型,所以將IE的事件模型調(diào)整為接近于DOM事件模型就可以了。 根據(jù)DOM屬性/方法與IE屬性/方法的不同,最后可得出如下的格式化event對象函數(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. 獲取事件對象 IE和DOM使用不同的方法來獲取event對象。在IE中,event對象是與window對象相關(guān)的,而在DOM中,它獨立于任何其他對象,并且是作為參數(shù)傳遞的。下面我們編寫一個通用的獲取event對象的函數(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對象,最后一節(jié)還創(chuàng)建了一個跨瀏覽器事件庫,可使用同一套方法來訪問事件對象,添加/刪除事件處理函數(shù),而無需考慮瀏覽器檢測的問題 |
|