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

看板Flash作者 (藍玥)時間11年前 (2013/08/30 19:30), 編輯推噓5(500)
留言5則, 5人參與, 最新討論串1/1
網誌圖文好讀版: 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 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 118.163.78.91

08/30 21:51, , 1F
好久不見的心得文 推推
08/30 21:51, 1F

08/30 23:30, , 2F
認真推~
08/30 23:30, 2F

08/31 16:05, , 3F
好文~ 推~~
08/31 16:05, 3F

09/11 10:02, , 4F
推一個
09/11 10:02, 4F

10/13 00:37, , 5F
FLASH新手 雖然只看得懂前面一小段也獲益良多@@ 推~
10/13 00:37, 5F
文章代碼(AID): #1I889iNX (Flash)
文章代碼(AID): #1I889iNX (Flash)