天天看點

AS3 事件流

AS3的事件流二個重要的應用知識  

  1. 在AS3的事件流應用過程中,會出現一些冒名奇妙的事情,但很多網站、很多教程上都沒有介紹這些不是BUG的BUG是如何産生的,其實與下面二個重要的應用知識有關。  
  2. 1、顯示層次結構改變與事件流:  
  3. 被通知某事件的事件對象清單順序,是先于事件排程之前被确定的。也就是說:一個事件排程開始至這個事件排程結束,所有事件流經過的對象顯示層次結構即便是被修改了,事件流經過對象的過程還是保持不變(附:事件流過程不變,但事實上顯示結構層次已經變了)。如,當一個顯示對象的子對象在事件流過程中被父對象的監聽器從顯示清單中移去,哪怕是被删除引用,事件流還是會經過子對象,如果子對象上存在監聽器,它的監聽器還是會被繼續執行。  
  4. 2、事件監聽器清單固化:  
  5. 在一個事件流過程中,事件被傳送到每一個對象時,該對象的監聽器清單将被固化,不可改變,如:在目前對象捕獲階段的監聽器中給目前對象繼續添加一個監聽器,将會無效,但他會在後面的事件流中生效,如添加一個冒泡階段的監聽器。事件被傳送到每一個對象時,該對象的監聽器清單雖然被固化,但它并不固化事件流中子對象的監聽器清單,仍然可以使用目前對象的監聽器移除或添加子對象的監聽器,并且在事件流到達子對象時,監聽器有效,監聽器清單在到達子對象時也是被固化的。  
  6. 事件流  
  7. 隻要發生事件,Flash Player就會調試事件對象。如果事件目标不在顯示清單中,則Flash Player将事件對象直接排程到事件目标。例如,Flash Player将Progress事件對象直接調試到URLStream對象。但是,如果事件目标在顯示清單中,則Flash Player将事件對象調試到顯示清單,事件對象将在顯示清單中穿行,直到到達事件目标。  
  8. “事件流”說明事件對象如何在顯示清單中穿行。顯示清單以一種可以描述為樹的層次結構形式進行組織。位于顯示清單層次結構頂部的是舞台,它是一種特殊的顯示對象容器,用作顯示清單的根。舞台由Flash.display.Stage類表示,且隻能通過顯示對象通路。每個顯示對象都有一個名為stage的屬性,該屬性表示應用程式的舞台。  
  9. 當Flash Player排程事件對象時,該事件對象進行一次從舞台到“目标節點”的往返行程。DOM事件規範将目标節點定義為代表事件目标的節點。也就是說,目标節點是發生了事件的顯示清單對象。  
  10. 從概念上來說, 事件流分為三部分。  
  11. 第一部分稱為捕獲階段,該階段包括從舞台到目标節點的父節點範圍内的所有節點。  
  12. 第二部分稱為目标階段,該階段僅包括目标節點。  
  13. 第三部分稱為冒泡階段。冒泡階段包括從目标節點的父節點傳回到舞台(從底到頂)的行程中遇到的節點。  
  14. 早期版本的ActionScript中沒有事件流,這意味着事件偵聽器隻能添加到生成事件的對象。在ActionScript 3.0中,您不但可以将事件偵聽器添加到目标節點,還可以将它們添加到事件流中的任何節點。  
  15. 不過,并所有事件對象都參與事件流的所有三個階段。某些類型的事件(例如enterFrame和init類型的事件)會直接排程到目标節點,并不參與捕獲階段和冒泡階段。其它事件可能以不在顯示清單中的對象為目标,例如排程到Socket類的執行個體的事件。這些事件對象也将直接流至目标對象,而不參與捕獲和冒泡階段  
  16. 總結:  
  17. 1.事件流是面向DisplayObject的一個過程機制,但凡顯示對象觸發的事件,必有這個流過程,自上而下,再自下而上  
  18. 2.事件流機制是在同一條路徑上的父子關系的顯示對象都會參與的(預設)  
  19. 4.最重要的一點就是,子對象觸發的事件,隻要父對象有偵聽,那麼無論如何,父對象都會觸發一次所偵聽的事件  
  20. 而且順序是子對象先觸發事件,然後父對象再觸發(這是由冒泡階段的順序觸發的)  
  21. 5.将addEventListener函數中的第三個參數設為true,則隻在捕獲階段偵聽,對于沒有子對象的元素,事件是不會觸發的,隻有當子對象同樣偵聽相同僚件時,才會觸發事件(因為沒有目标階段)  
  22. 反正要了解事件機制,三個階段的執行順序及執行因素了解好後,下面的原理就很好了解了  
  23. 如果設定addEventListener函數的第三個參數為true,會中斷目标階段的檢測,但它始終會參加事件流,  
  24. 是以ROLL_OVER和ROLL_OUT是實作不  參加事件流(捕獲和冒泡均不參加)操作的方法 

當事件發生時,flash播放器會自動顯示與此事件相關的行為,因為這個行為是由Flash播放器自動顯示的,所 以這樣的行為稱為預設行為。 

例如,在一個輸入文本的執行個體中,當使用者輸入文本時,會觸發"TextEvent.TEXT_INPUT"事件,這時flash會把 

文本顯示出來,"顯示輸入的文本"這個行為即預設行為。 

例如,當滑鼠停在按鈕上時,會觸發"MouseEvent.ROLL_OVER"事件,這時按鈕上的文字會高亮顯示,"高亮 

顯示"這個行為也是預設行為。 

當然,可以通過preventDefault() 方法來阻止預設行為的發生 

input_txt.addEventListener(TextEvent.TEXT_INPUT,func) 

function func(e:TextEvent){ 

  //不使用預設行為 

  e.preventDefault() 

如何知道preventDefault()是否被調用,可用isDefaultPrevented () 方法來測試,true代表調用,false代表 

沒有調用 

注意幾點: 

1、不是所有事件對象相關的預設行為都能被阻止(如click事件對象) 

如何知道一個預設行為是否能阻止呢?可以使用Event類的cancelable屬性 

參考代碼: 

input_txt.addEventListener(TextEvent.TEXT_INPUT,func) 

function func(e:TextEvent){ 

  trace(e.cancelable) 

//TextEvent是Event類的子類,是以具有Event類的cancelable屬性 

2、不是所有事件對象都有相關的預設行為(如:connect事件對象) 

3、預設行為不存在于自定義事件對象

as3事件處理-事件流

事件流(event flow)

首先得明白兩個術語:display list與node

一個flash應用程式可能會非常複雜,比如,有很多可視執行個體嵌套在一起,這樣的話會形成一個樹形結構,這個結構的根是stage,然後一級級到不同的執行個體,一般來說,要把這個樹形結構倒過來看,即stage在頂部,在stage中的執行個體一級級排列在下面,要參考幫助中的圖。

這樣的一個樹狀結構即display list,每個執行個體(stage也是執行個體)都是樹中的一個節點(node),如何來處理這種複雜結構的事件呢?as3引入了事件流的概念

事件流用于描述事件發生在display list中,周遊其所有node的過程,它可以分為3個階段:

1、捕獲階段(capture phase):從頂部(如stage)到目标

2、目标階段(target phase):目标

3、冒泡階段(bubbling phase):從目标到頂部

看一個例子:

1、建立一個display list,其包含了4個可視執行個體,root1,mc1,mc2,mc3

import flash.display.*

var mc1=new Sprite()

var mc2=new Sprite()

var mc3=new Sprite()

//this代表root1

this.addChild(mc1)

mc1.addChild(mc2)

mc2.addChild(mc3)

drawRect(mc1,0xff9900,200)

drawRect(mc2,0x0000FF,100)

drawRect(mc3,0xffbbff,50)

//繪制矩形

function drawRect(obj,c,l){

  obj.graphics.beginFill(c)

  obj.graphics.drawRect(0,0,l,l)

}

2、為display list中的所有執行個體注冊click事件偵聽器

this.addEventListener("click",clickFunc)

mc1.addEventListener("click",clickFunc)

mc2.addEventListener("click",clickFunc)

mc3.addEventListener("click",clickFunc)

function clickFunc(evt:Event){  

  trace(evt.currentTarget.name+" is click")

  }

}

3、測試一下,單擊最小的矩形,看看事件的執行順序

instance3 is click

instance2 is click

instance1 is click

root1 is click

從順序中可以看出,事件流采用了冒泡機制,即從單擊的目标(instance3)開始,向頂部流動,最後到達root1。

通過

trace(evt.eventPhase)

可以知道事件流的階段,結果如下:

instance3 is click

2

instance2 is click

3

instance1 is click

3

root1 is click

3

2代表目标階段,相應的執行個體即你所單擊的執行個體,3代表冒泡階段。

如果要使事件流使用捕獲機制,在注冊偵聽時應多加一個參數,把useCapture參數設定為true

this.addEventListener("click",clickFunc,true)

如果兩種機制都要使用,須注冊兩次偵聽器,useCapture的的值分别為true,false

事件對象是Event類的執行個體,具有多個屬性,其中target與currentTarget屬性必須把它們分精楚。

對于一個簡單的事件處理過程,厘清target與currentTarget并沒有必要,因為它們一般指向同一個對象,如對一個簡單的mc容器注冊偵聽器,在處理事件過程中,這兩個屬性都指向了這個mc。

但在一個相對複雜的display list中,這兩屬性是不相同的,比如,在主場景中有一個執行個體名為mc的影片剪輯執行個體,此mc包含了一個子mc,假設執行個體名為mc1

如果為父級即mc注冊一個click事件偵聽器,當單擊mc時,target與currentTarget都指向mc,當單擊mc1時,target指向mc1,而currentTarget指向mc,是以,在很多應用中,可能有人會認為currentTarget會指向父級。

如果為子級和父級都注冊一個偵聽器,那target是指單擊的目标,而currentTarget是指在處理事件(即活動)的目标,因為as3的事件處理有3個階段(捕獲、目标、冒泡),并且預設時采用冒泡機制,當單擊子級mc1時,currentTarget應先指向底層,并向上冒泡,即先指向mc1,再指向mc

是以,currentTarget屬性應具備兩條件,一是它注冊了偵聽器,二是正在處理事件,而target就指事件流中的target。例如,單擊了mc1,不管事件如何冒泡(不管currentTarget指向誰),target都指向mc1,

小結:target屬性在事件流的目标階段,而currentTarget屬性在事件流的冒泡階段(如currentTarget有時指父級)和目标階段(兩屬性的指向相同),當然也可以是捕獲階段。

                                                                                      (轉載)

as3