JavaScript事件的理解

來源:互聯網
上載者:User
在很多語言的學習中,“事件”都是一個比較難理解,但是又是一個很重要的概念。JavaScript中的事件處理也是一樣,正因為有了事件處理,才會出現Ajax拖動的效果。本文就討論一下JavaScript中的事件處理,讀過之後,您就會知道,很多Ajax架構實現拖動效果的原理了。

一、 IE Event對象
(一)IE Event對象的主要屬性和方法
  在IE中有一個專門負責事件處理的對象Event,這個對象負責對事件的處理,含有很多的屬性和方法,通過這些方法和屬性的調用,就能完成很多的事件處理。
  type:事件的類型,就是HTML標籤屬性中,沒有“on”首碼之後的字串,例如“Click”就代表單擊事件。
  srcElement:事件來源,就是發生事件的元素。
  button:聲明了被按下的滑鼠鍵,是一個整數。1代表滑鼠左鍵,2代表滑鼠右鍵,4代表滑鼠的中間鍵,如果按下了多個滑鼠鍵,就把這些值加在一起,所以3就代表左右鍵同步選取。
  clientX/clientY:是指事件發生的時候,滑鼠的橫、縱座標,返回的是整數,它們的值是相對於包容視窗的左上方產生的。
  offsetX/offsetY:滑鼠指標相對於源元素的位置,可以確定單擊Image對象的哪個象素。
  altKey,ctrlKey,shiftKey:顧名思義,這些屬性是指滑鼠事件發生的時候,是否同時按住了Alt、Ctrl或者Shift鍵,返回的是一個布爾值。
  keyCode:返回keydown和keyup事件發生的時候,按鍵的代碼以及keypress事件的Unicode字元。
  fromElement、toElement前者是指代mouseover事件移動過的文件項目,後者指代mouseout事件中滑鼠移動到的文件項目。
  cancelBubble:一個布爾屬性,把它設定為true的時候,將停止事件進一步起泡到包容層次的元素。
  returnValue:一個布爾值屬性,設定為false的時候可以組織瀏覽器執行預設的事件動作,相當於<a href=”#” onclick=”ProcessMethod();return false;” />。
  attachEvent()和detachEvent()方法:為制定DOM對象事件類型註冊多個事件處理函數的方法,它們有兩個參數,第一個是事件類型,第二個是事件處理函數。在attachEvent()事件執行的時候,this關鍵字指向的是window對象,而不是發生事件的那個元素。
  (二)IE Event對象的一些說明
  1.IE Event對象是一個全域屬性
  在IE中,不能把Event對象作為參數傳遞給事件處理程式,只能用window.event或者event來引用Event對象。因為在IE中,Event是window的一個屬性,也就是說event是一個全域變數,這個變數提供了事件的細節。
  2.IE中事件的起泡:IE中事件可以沿著包容層次一點點起泡到上層,也就是說,下層的DOM節點定義的事件處理函數,到了上層的節點如果還有和下層相同事件類型的事件處理函數,那麼上層的事件處理函數也會執行。例如,<div>標籤包含了<a>,如果這兩個標籤都有onclick事件的處理函數,那麼執行的情況就是先執行<a>標籤的onclick事件處理函數,再執行<div>的事件處理函數。如果希望<a>的事件處理函數執行完畢之後,不希望執行上層的<div>的onclick的事件處理函數了,那麼就把cancelBubble設定為false即可。
  
二、 IE中拖動DOM元素的例子
/*
  該函數由mousedown事件處理調用
  它為隨後發生的mousemove和mouseup事件註冊了臨時的捕捉事件處理常式
  並用這些事件處理常式拖動指定的文件項目
  第二個參數必須是mousedown事件的事件對象
*/
function beginDrag(elementToDrag,event)
{
  //該元素當前位於何處
  //該元素的樣式性質必須具有left和top css屬性
  //此外,我們假定他們用象素做單位
  //var x=parseInt(elementToDrag.style.left);
  //var y=parseInt(elementToDrag.style.top);
 
  //計算一個點和滑鼠點擊之間的距離,下面的嵌套的moveHandler函數需要這些值
  var deltaX=event.clientX-parseInt(elementToDrag.style.left);
  var deltaY=event.clientY-parseInt(elementToDrag.style.top);
 
//  註冊mousedown事件後發生的mousemove和mouseup事件的處理常式
//  注意,它們被註冊為文檔的捕捉事件處理常式
//  在滑鼠按鍵保持按下的狀態的時候,這些事件處理常式保持活動的狀態
//  在按鈕被釋放的時候,它們被刪除
  document.attachEvent("onmousemove",moveHandler);
  document.attachEvent("onmouseup",upHandler);
  
  //我們已經處理了該事件,不要讓別的元素看到它
 event.cancelBubble=true;
 event.returnValue=false;
 
  /*
    這是在元素被拖動時候捕捉mousemove事件的處理常式,它響應移動的元素
   
  */
  function moveHandler(e) 
  {
    //把元素移動到當前的滑鼠位置
    e=window.event;
    elementToDrag.style.left=(event.clientX-deltaX)+"px";
    elementToDrag.style.top=(event.clientY-deltaY)+"px";
   
    //不要讓別的元素看到該事件
    event.cancelBubble=true;
   
  }
 
  /*
    該事件將捕捉拖動結束的時候發生的mouseup事件
  */
  function upHandler(e)
  {
    //登出事件處理常式
      document.detachEvent("onmouseup",upHandler);
      document.detachEvent("onmousemove",moveHandler);}
  
      event.cancelBubble=true;
    } 
   調用它的HTML檔案代碼:
 <html>
 <head>
     <title>Untitled Page</title>
     <script type="text/javascript" src="dragIE.js"></script>
 </head>
 <body>
 <div style="position:absolute;left:100px;top:100px;background-color:White;border:solid black;">
   <div style="background-color:Gray;border-bottom:solid black;padding:3px;font-family:Sans-Serif;font-weight:bold;" onmousedown="beginDrag(this.parentNode,event);">
   拖動我&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
   </div>
   <div>
   <p>This is a test.Testing,testing</p></div>
 </div>
 </body>
三、 DOM中的進階事件處理
 IE 6中的事件處理,並不是W3C DOM標準的事件處理模型,所以如果上述代碼運行在Mozilla Firefox的瀏覽器中,就會失去作用,同時即將發布的IE 7也將支援W3C DOM的二級標準,所以掌握DOM的進階事件處理顯得就很重要了,因為W3C DOM二級標準是未來Web的發展方向,同時W3C DOM的API非常常用,為未來更加複雜的Web開發提供了良好的基礎。
(一)事件處理常式的範圍和事件的傳播
  在正式討論DOM進階事件處理之前,我們有必要瞭解一下事件處理常式的範圍。事件處理常式的範圍要比普通的函數範圍複雜很多。普通的函數範圍鏈比較容易,例如在一個普通函數中尋找一個變數a,那麼JavaScript解譯器會先在該函數的調用對象中尋找是否有a這個變數,如果沒有,將會在範圍鏈的下一個對象,一般是全域對象中尋找。但是事件處理常式沒這麼簡單,特別是用HTML的屬性定義的,它們的範圍鏈的頭部是調用它們的對象,而下一個對象並不是全域對象,而是觸發事件處理常式的對象。這樣就會出現一個問題,window和document都有一個方法open(),如果open()前面不加修飾,那麼在事件處理的函數中將會調用document.open()方法,而不是常用的window.open()方法,所以使用的時候應該明確指明是window.open()。
(二)事件傳播和註冊事件處理常式
1.事件傳播
  在二級DOM標準中,事件處理常式比較複雜,當事件發生的時候,目標節點的事件處理常式就會被觸發執行,但是目標節點的父節點也有機會來處理這個事件。事件的傳播分為三個階段,首先是捕捉階段,事件從Document對象沿著DOM樹向下傳播到目標節點,如果目標的任何一個父節點註冊了捕捉事件的處理常式,那麼事件在傳播的過程中就會首先運行這個程式。下一個階段就是發生在目標節點自身了,註冊在目標節點上的相應的事件處理常式就會執行;最後是起泡階段,事件將從目標節點向上傳回給父節點,同樣,如果父節點有相應的事件處理常式也會處理。在IE中,沒有捕捉的階段,但是有起泡的階段。可以用stopPropagating()方法來停止事件傳播,也就是讓其他元素對這個事件不可見,在IE 6中,就是把cancelBubble設定為true。
2.註冊事件處理常式
  和IE一樣,DOM標準也有自己的事件處理常式,不過DOM二級標準的事件處理常式比IE的強大一些,事件處理常式的註冊用addEventListner方法,該方法有三個參數,第一個是事件類型,第二個是處理的函數,第三個是一個布爾值,true表示制定的事件處理常式將在事件傳播的階段用於捕捉事件,否則就不捕捉,當事件發生在對象上才觸發執行這個事件處理的函數,或者發生在該對象的位元組點上,並且向上起泡到這個對象上的時候,觸發執行這個事件處理的函數。例如:document.addEventListener("mousemove",moveHandler,true);就是在mousemove事件發生的時候,調用moveHandler函數,並且可以捕捉事件。
  可以用addEventListener為一個事件註冊多個事件處理的程式,但是這些函數的執行順序是不確定,並不像C#那樣按照註冊的順序執行。
  在Mozilla Firefox中用addEventListener註冊一個事件處理常式的時候,this關鍵字就表示呼叫事件處理常式的文件項目,但是其他瀏覽器並不一定是這樣,因為這不是DOM標準,正確的做法是用currentTarget屬性來引用呼叫事件處理常式的文件項目。
3.二級DOM標準中的Event
  和IE不同的是,W3C DOM中的Event對象並不是window全域對象下面的屬性,換句話說,event不是全域變數。通常在DOM二級標準中,event作為發生事件的文檔對象的屬性。Event含有兩個子介面,分別是UIEvent和MutationEvent,這兩個子介面實現了Event的所有方法和屬性,而MouseEvent介面又是UIEvent的子介面,所以實現了UIEvent和Event的所有方法和屬性。下面,我們就看看Event、UIEvent和MouseEvent的主要屬性和方法。
  1.Event
    type:事件類型,和IE類似,但是沒有“on”首碼,例如單擊事件只是“click”。
    target:發生事件的節點。
    currentTarget:發生當前正在處理的事件的節點,可能是Target屬性所指向的節點,也可能由於捕捉或者起泡,指向Target所指節點的父節點。
    eventPhase:指定了事件傳播的階段。是一個數字。
    timeStamp:事件發生的時間。
    bubbles:指明該事件是否起泡。
    cancelable:指明該事件是否可以用preventDefault()方法來取消預設的動作。
    preventDefault()方法:取消事件的預設動作;
    stopPropagation()方法:停止事件傳播。
  2.UIEvent
    view:發生事件的window對象。
    detail:提供事件的額外資訊,對於單擊事件、mousedown和mouseup事件都代表的是點擊次數。
  3.MouseEvent
   button:一個數字,指明在mousedown、mouseup和單擊事件中,滑鼠鍵的狀態,和IE中的button屬性類似,但是數字代表的意義不一樣,0代表左鍵,1代表中間鍵,2代表右鍵。
   altKey、ctrlKey、shiftKey、metaKey:和IE相同,但是IE沒有最後一個。
   clientX、clientY:和IE的含義相同,但是在DOM標準中,這兩個屬性值都不考慮文檔的滾動情況,也就是說,無論文檔滾動到哪裡,只要事件發生在視窗左上方,clientX和clientY都是0,所以在IE中,要想得到事件發生的座標相對於文檔開頭的位置,要加上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;
   
  }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.