[心得] AS3的事件傳遞機制

作者: cochiachang (藍玥)   2013-08-30 19:30:49
網誌圖文好讀版: http://ppt.cc/sygC
=============================================
當事件被發送出來之後。Event一般來?都會有一個Flow。 Flow分三個部分:
Capture(捕獲階段)
Targeting(目標階段)
Bubbling(冒泡階段)
其關係圖如下:
http://claire-chang.com/wp-content/uploads/2013/08/efAzj.jpg
值得一提的是,在FLASH裡,只有和UI相關的物件
會有上圖所示的目標及補獲階段的事件流,
一般像是Timer、Loader事件,是直接進入目標階段,並不會有下圖所示的事件流的流程。
在宣告Event時,也可以先指定事件是否要完整的跑完全部的流程。
var event:Event = new Event(type, bubbles, cancelable);
參數說明(官方文件)
type:String是要發送的事件的識別名稱EX:Event.COMPLETE
bubbles:Boolean預設值是false,這個值是用來設定是否要有冒泡階段,
如果傳false,代表他不會跑完全部的流程,只會從Capture到target階段就停止。
cancelable:Boolean預設值是false,
這個值是用來設定是否這個事件可以被event.preventDefault();取消,
如果設定為true的話,代表此事件是可以被取消的
(稍候在dispatchEvent會更詳述這部份)。
常用的可以取消的事件有(cancelable為true):
FocusEvent.MOUSE_FOCUS_CHANGE
FocusEvent.KEY_FOCUS_CHANGE
TextEvent.TEXT_INPUT。
而發送事件則是用這一段程式碼:
var result:Boolean = box.dispatchEvent(event);
在發送事件時,要注意,假使今天我們是在STAGE裡面有一個box物件,
那當我們用box.dispatchEvent(event);
即使事件是用box發送的,事件還是會從stage > root > box這樣跑。(請見上圖)
假如在建立Event時,bubbles設為true,
那在上圖跑的流程為stage > root > box > root > stage。
而若bubbles設為false,跑的流程則是stage > root > box
當我們用root.dispatchEvent(event);時
bubbles設為true,上圖跑的流程為stage > root > stage
bubbles設為false,流程為stage > root
由此可知,事件流只會到目標(Target),就會停止往下傳。
假如今天box裡面有一個物件button,若是用box.dispatchEvent(event),
button物件是不會接到事件流的。(因為到目標階段便會開始bubbles或停止)
並且假如今天root裡同時有box和box2兩個物件,
假使我們用box.dispatchEvent(event),則box2也不會接到事件。
至於第三個在建立Event的參數cancelable,不論值是true或false,
都不會影響事件流的流程。
那他的作用是做什麼的呢?
我們可以發現,dispatchEvent有回傳一個布林值,
cancelable就是在影響這個布林值的傳回參數。
今天我們假如要創建一個物件,
但是要讓使用者有權力去阻止這個事件發生後的後續發展時,可以這樣寫
if(this.dispathEvent(event)){
trace("success!");
//在這寫後續發展
}
假使使用者在監聽的途中呼叫 event.preventDefault();,
並且EVENT的cancelable為true時,dispatchEvent回傳的值就會是false,
便不會執行trace("success!");那塊區塊。
但假使EVENT的cancelable為false時,
不論你在事件執行中有沒有呼叫event.preventDefault(),
dispatchEvent回傳的值就會是true。
一般我們會在傳遞事件的途中,去將事件攔截下來。增加監聽事件的程式碼如下
box.addEventListener(MouseEvent.MOUSE_DOWN,parent1Event);
官網關於addEventListener的說明如下
addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
傳入的參數意義如下:
type(String):事件名稱
listener(Function):要執行的Function
useCapture(Boolean):這個和本篇要說的事件流有關,當今天傳入的值為true,
則只能在補獲階段去抓取事件,在冒泡階段是聽不到的。
如果將 useCapture 設置為 true,則偵聽器只在捕獲階段處理事件,
而不在目標或冒泡階段處理事件。如果 useCapture 為 false,
則偵聽器只在目標或冒泡階段處理事件。
要在所有三個階段都偵聽事件,需註冊 addEventListener 兩次:
一次將 useCapture 設置為 true,一次將 useCapture 設置為 false。
不過要注意的是,當今天若useCapture為true時,並不會聽到target階段時的事件,
但若為false時,也可以聽到target階段時的事件。
假使今天我們用box.dispatchEvent(event);來發送事件,
然後box的監聽事件的useCapture設為true。
ex : box.addEventListener(MouseEvent.CLICK, rootClick, true);
這樣rootClick事件並不會被呼叫到。
若box的監聽事件的useCapture設為false 。
ex : box.addEventListener(MouseEvent.CLICK, rootClick, false);
這樣rootClick事件便會被呼叫到。
priority(int):若今天同時有很多個監聽器同時監聽同一事件,
可用這個值來設定那一個監聽器應該被優先執行。
數字愈高代表會愈快執行該事件偵聽程式。
useWeakReference(Boolean):是否使用弱關連。
若是用弱關連,當被監聽的物件所指到的變數被指向記憶體的其他地方,
這個關係也會一併被取消(物件會被GC回收)。
但如果傳進的值是false,當今天被監聽的物件的其他關連被指向別處時,
該物件不會被GC回收,需要手動removeEventListener時,該物件才會被GC回收。
除了上述的幾個參數外,還有幾個函數可以中斷事件流的流程。
那就是stopPropagation()和stopImmediatePropagation()
這兩個可以停止事件流繼續下去。
那這兩個函數有什麼差別呢?
下圖可以很清楚的解釋差異:
stopPropagation():會把同一階層的其他事件跑完才停止。
圖: http://claire-chang.com/wp-content/uploads/2013/08/5MYe3.jp
stopImmediatePropagation():立刻停止之後所有的事件流。
圖: http://claire-chang.com/wp-content/uploads/2013/08/jleAX.jpg
假如今天box同時有兩個監聽函數如下
box.addEventListener(MouseEvent.MOUSE_DOWN,eventMouseDownHandler1,false,1);
box.addEventListener(MouseEvent.MOUSE_DOWN,eventMouseDownHandler2,false,2);
則由於priority值的關係,
eventMouseDownHandler2 會先被執行,
eventMouseDownHandler1 在之後才被呼叫。
那若是在eventMouseDownHandler2裡面呼叫event.stopPropagation(),
eventMouseDownHandler1還是會被執行才將事件流中斷。
但是若在eventMouseDownHandler2裡面呼叫event.stopImmediatePropagation(),
則eventMouseDownHandler1就不會被呼叫到了
網誌好讀版: http://claire-chang.com/1054-as3的事件傳遞機制
延伸閱讀:
hasEventListener()與willTrigger()區別
http://ppt.cc/sqKU
作者: onchin (炸蝦豬排丼)   0000-00-00 00:00:00
FLASH新手 雖然只看得懂前面一小段也獲益良多@@ 推~
作者: viceversa56 (姊超猛)   2013-08-30 21:51:00
好久不見的心得文 推推
作者: lulu7953 (lulu)   2013-08-30 23:30:00
認真推~
作者: newton510 (~~~)   2013-08-31 16:05:00
好文~ 推~~
作者: BIAN (shu)   2013-09-11 10:02:00
推一個

Links booklink

Contact Us: admin [ a t ] ucptt.com