三、 DOM中的高級事件處理
IE 6中的事件處理,并不是W3C DOM標準的事件處理模型,所以如果上述代碼運行在Mozilla Firefox的瀏覽器中,就會失去作用,同時即將發(fā)布的IE 7也將支持W3C DOM的二級標準,所以掌握DOM的高級事件處理顯得就很重要了,因為W3C DOM二級標準是未來Web的發(fā)展方向,同時W3C DOM的API非常常用,為未來更加復雜的Web開發(fā)提供了良好的基礎。
(一)事件處理程序的作用域和事件的傳播
在正式討論DOM高級事件處理之前,我們有必要了解一下事件處理程序的作用域。事件處理程序的作用域要比普通的函數(shù)作用域復雜很多。普通的函數(shù)作用域鏈比較容易,例如在一個普通函數(shù)中查找一個變量a,那么JavaScript解釋器會先在該函數(shù)的
調(diào)用對象中查找是否有a這個變量,如果沒有,將會在作用域鏈的下一個對象,一般是全局對象中查找。但是事件處理程序沒這么簡單,特別是用HTML的屬性定義的,它們的作用域鏈的頭部是調(diào)用它們的對象,而下一個對象并不是全局對象,而是觸發(fā)事件處理程序的對象。這樣就會出現(xiàn)一個問題,window和document都有一個方法open(),如果open()前面不加修飾,那么在事件處理的函數(shù)中將會調(diào)用document.open()方法,而不是常用的window.open()方法,所以使用的時候應該明確指明是window.open()。
(二)事件傳播和注冊事件處理程序
1.事件傳播
在二級DOM標準中,事件處理程序比較復雜,當事件發(fā)生的時候,目標節(jié)點的事件處理程序就會被觸發(fā)執(zhí)行,但是目標節(jié)點的父節(jié)點也有機會來處理這個事件。事件的傳播分為三個階段,首先是捕捉階段,事件從Document對象沿著DOM樹向下傳播到目標節(jié)點,如果目標的任何一個父節(jié)點注冊了捕捉事件的處理程序,那么事件在傳播的過程中就會首先運行這個程序。下一個階段就是發(fā)生在目標節(jié)點自身了,注冊在目標節(jié)點上的相應的事件處理程序就會執(zhí)行;最后是起泡階段,事件將從目標節(jié)點向上傳回給父節(jié)點,同樣,如果父節(jié)點有相應的事件處理程序也會處理。在IE中,沒有捕捉的階段,但是有起泡的階段。可以用stopPropagating()方法來停止事件傳播,也就是讓其他元素對這個事件不可見,在IE 6中,就是把cancelBubble設置為true。
2.注冊事件處理程序
和IE一樣,DOM標準也有自己的事件處理程序,不過DOM二級標準的事件處理程序比IE的強大一些,事件處理程序的注冊用addEventListner方法,該方法有三個參數(shù),第一個是事件類型,第二個是處理的函數(shù),第三個是一個布爾值,true表示制定的事件處理程序將在事件傳播的階段用于捕捉事件,否則就不捕捉,當事件發(fā)生在對象上才觸發(fā)執(zhí)行這個事件處理的函數(shù),或者發(fā)生在該對象的字節(jié)點上,并且向上起泡到這個對象上的時候,觸發(fā)執(zhí)行這個事件處理的函數(shù)。例如:document.addEventListener("mousemove",moveHandler,true);就是在mousemove事件發(fā)生的時候,調(diào)用moveHandler函數(shù),并且可以捕捉事件。 可以用addEventListener為一個事件注冊多個事件處理的程序,但是這些函數(shù)的執(zhí)行順序是不確定,并不像C#那樣按照注冊的順序執(zhí)行。 在Mozilla Firefox中用addEventListener注冊一個事件處理程序的時候,this關鍵字就表示調(diào)用事件處理程序的文檔元素,但是其他瀏覽器并不一定是這樣,因為這不是DOM標準,正確的做法是用currentTarget屬性來引用調(diào)用事件處理程序的文檔元素。
3.二級DOM標準中的Event
和IE不同的是,W3C DOM中的Event對象并不是window全局對象下面的屬性,換句話說,event不是全局變量。通常在DOM二級標準中,event作為發(fā)生事件的文檔對象的屬性。Event含有兩個子接口,分別是UIEvent和MutationEvent,這兩個子接口實現(xiàn)了Event的所有方法和屬性,而MouseEvent接口又是UIEvent的子接口,所以實現(xiàn)了UIEvent和Event的所有方法和屬性。下面,我們就看看Event、UIEvent和MouseEvent的主要屬性和方法。
1.Event
type:事件類型,和IE類似,但是沒有“on”前綴,例如單擊事件只是“click”。
target:發(fā)生事件的節(jié)點。
currentTarget:發(fā)生當前正在處理的事件的節(jié)點,可能是Target屬性所指向的節(jié)點,也可能由于捕捉或者起泡,指向Target所指節(jié)點的父節(jié)點。
eventPhase:指定了事件傳播的階段。是一個數(shù)字。
timeStamp:事件發(fā)生的時間。
bubbles:指明該事件是否起泡。
cancelable:指明該事件是否可以用preventDefault()方法來取消默認的動作。
preventDefault()方法:取消事件的默認動作;
stopPropagation()方法:停止事件傳播。
2.UIEvent
view:發(fā)生事件的window對象。
detail:提供事件的額外信息,對于單擊事件、mousedown和mouseup事件都代表的是點擊次數(shù)。
3.MouseEvent
button:一個數(shù)字,指明在mousedown、mouseup和單擊事件中,鼠標鍵的狀態(tài),和IE中的button屬性類似,但是數(shù)字代表的意義不一樣,0代表左鍵,1代表中間鍵,2代表右鍵。
altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE沒有最后一個。
clientX、clientY:和IE的含義相同,但是在DOM標準中,這兩個屬性值都不考慮文檔的滾動情況,也就是說,無論文檔滾動到哪里,只要事件發(fā)生在窗口左上角
clientX和clientY都是0,所以在IE中,要想得到事件發(fā)生的坐標相對于文檔開頭的位置,要加上document.body.scrollLeft和document.body.scrollTop。
screenX、screenY:鼠標指針相對于顯示器左上角的位置,如果你想打開新的窗口,這兩個屬性很重要。
relatedTarget:和IE中的fromElement、toElement類似,除了對于mouseover
mouseout有意義外,其他的事件沒什么意義。
(三)兼容于兩種主流瀏覽器的拖動DOM元素的例子
好了,剛才講了這么多DOM編程和IE中的事件,那么如何編寫兼容IE和Mozilla Firefox兩種主流瀏覽器的拖拽程序呢?代碼如下:
function beginDrag(elementToDrag,event) { var deltaX=event.clientX-parseInt(elementToDrag.style.left); var deltaY=event.clientY-parseInt(elementToDrag.style.top); if(document.addEventListener) { document.addEventListener("mousemove",moveHandler,true); document.addEventListener("mouseup",upHandler,true); } else if(document.attachEvent) { document.attachEvent("onmousemove",moveHandler); document.attachEvent("onmouseup",upHandler); } if(event.stopPropagation) event.stopPropagation(); else event.cancelBubble=true; if(event.preventDefault) event.preventDefault(); else event.returnValue=false; function moveHandler(e) { if (!e) e=window.event; //如果是IE的事件對象,那么就用window.event //全局屬性,否則就用DOM二級標準的Event對象。 elementToDrag.style.left=(event.clientX-deltaX)+"px"; elementToDrag.style.top=(event.clientY-deltaY)+"px"; if(event.stopPropagation) event.stopPropagation(); else event.cancelBubble=true; } function upHandler( e) { if(document.removeEventListener) { document.removeEventListener("mouseup",upHandler,true); document.removeEventListener("mousemove",moveHandler,true);} else { document.detachEvent("onmouseup",upHandler); document.detachEvent("onmousemove",moveHandler);} } if(event.stopPropagation) event.stopPropagation(); else event.cancelBubble=true; }
經(jīng)典論壇交流: http://bbs.blueidea.com/thread-2837961-1-1.html
本文鏈接:http://www.95time.cn/tech/web/2008/5512.asp
出處:藍色理想
責任編輯:moby
上一頁 IE中拖動DOM元素的例子 下一頁
◎進入論壇網(wǎng)頁制作、WEB標準化版塊參加討論,我還想發(fā)表評論。
|