天天看點

AS3 event flow 事件冒泡機制

=思路大綱=

  1. ActionScript 2的問題
  2. AS3解決問題
  3. 結合問題,說明“冒泡”
  4. 冒泡的問題所在以及解決方法

1 - ActionScript 2的問題

stage裡有一個mc,mc裡有一個btn

點選mc實作拖動mc,滑鼠松開停止拖動

點選mc實作mc隐藏。

最容易想到的方法,代碼如下:

mc.onPress = function() {         this.startDrag(); }; mc.onRelease = function() {         this.stopDrag(); }; mc.btn.onPress = function() {         mc._visible=false };

表面來看,這個思路是正确的。(實際上沒什麼思路可言,很簡單的方法。)

實際怎麼樣?當然是不能實作。

問題:點選btn,不能觸發btn的動作!!!!

解釋: 因為btn處于mc内部,mc被加上了事件以後,按照as2的事件機制,mc内部的btn甚至是其他的元件都不能接受事件。或者可以認為mc的事件覆寫了mc中其他元件的事件。

從非冒泡機制來說,在btn上點選滑鼠,首先接受到點選事件的自然是btn的上一層(也就是mc),然後才是btn元件。Mc先接受到點選事件,觸發相關的函數。然後呢?我們要實作的點選btn的效果沒了。我們可以認為mc把我們的滑鼠點選事件據為私有了,不再往下傳遞。(如果是冒泡機制的話,這個動作就回繼續往下傳遞到btn,然後btn會執行。)那麼這種效果在as2中還能實作麼?答案自然是肯定的,不過方法就複雜了。

這裡就不讨論了。As3已經成為主流。

但是as3中的冒泡機制,讓我們可以簡單的解決這樣的難題。

2 - AS3解決問題

下面來看as3中怎麼實作。

代碼如下:

import flash.events.*;

mc.addEventListener(MouseEvent.CLICK,mcfunction); mc.btn.addEventListener(MouseEvent.CLICK,btnfucntion);

function mcfunction(event:MouseEvent) {

        trace("mc click");

}

function btnfucntion(event:MouseEvent) {

        trace("btn click");

}

看看代碼就覺得,好像沒用什麼特别的解決方法,就加兩個偵聽函數,就搞定了。

這個代碼自然的不能再自然了,就好像做flash 先的安裝軟體一樣。

但是如此自然的代碼下面,使AS3的冒泡機制在提供支援。

3 - 結合問題,說明冒泡機制:

Help中有一個冒泡機制的圖,相信大家都已經看過了

這裡我聯系執行個體,另外做一個圖,幫助各位了解。

AS3 event flow 事件冒泡機制
AS3 event flow 事件冒泡機制

上圖為as2中的執行原理

下圖為as3中的執行原理

AS3 event flow 事件冒泡機制

上圖也就是在as3中實作我們文章開始提出的例子的工作原理。

下面較長的描述一下

捕獲階段: 

滑鼠在btn上發出點選事件,首先捕捉到該事件的事stage.,然後事件往下傳遞到mc,再到btn..(如果滑鼠事件發生在btn按鈕中的一個 label上,那麼該事件還會繼續向下傳遞,直到找到label元件。)AS2中,一旦找到了可以相應事件的函數,就停止了,不會往下傳遞。這個道理應該說明白了

目标階段 :

找到我們的滑鼠最底層的目标,也就是btn以後,那麼就開始執行btn的偵聽函數了。

    如果滑鼠事件發生的所在位置,是mc中的btn中的一個label。那麼将先執行label的偵聽函數。(當然我們的例子中沒有label)

冒泡階段:

執行了目标階段的偵聽函數以後,開始冒泡。

換一個說法是,傳回btn的父級元件mc,如果能找到相關的偵聽函數,那麼就執行,如果沒有,就繼續往上冒泡到btn的父級元件mc的父級元件stage。看能不能找到相關的偵聽函數。

注意一個:首先執行的函數一定是目标對象的偵聽函數。就像我們上面的例子一樣,點選btn會先trace(“btn click”),然後冒泡到mc,執行trace(“mc click”)..然後繼續往上,如果stage我們也加一個偵聽函數,執行語句,那麼還會繼續執行 trace(“stage click”).

到達stage頂層了,冒泡結束。

說到這裡,各位看官也應該明白了as3的冒泡究竟是幹什麼用的了

4 - 冒泡的問題所在以及解決方法 

冒泡也有問題,并不是說它有缺陷,因為出現問題無法避免。

問題在于,

假如在上面的例子中,我們不想在點選btn冒泡階段中執行mc的偵聽函數,我們隻想執行btn的偵聽函數。怎麼解決?

同樣的問題延伸出去,可以得到很多擴充和應用。

那麼我們需要阻止他的冒泡的時候執行相關的偵聽函數。

Chm中的方法有

stopImmediatePropagation():void

防止對事件流中目前節點中和所有後續節點中的事件偵聽器進行處理。

stopPropagation():void

防止對事件流中目前節點的後續節點中的所有事件偵聽器進行處理。

用來修改我們上面的例子

代碼如下:

import flash.events.*; mc.addEventListener(MouseEvent.CLICK,mcfunction); mc.btn.addEventListener(MouseEvent.CLICK,btnfucntion); function mcfunction(event:MouseEvent) {         trace("mc click"); } function btnfucntion(event:MouseEvent) {         trace("btn click");         event.stopPropagation();//修改在此處。簡單一句,解決問題 }

現在可以試試,點選btn運作得到的結果就是

代碼:

btn click

說明,已經防止了冒泡階段中對mc偵聽函數的處理。也就沒有trace(“mc click”)了

As3事件機制遠遠不像這裡寫的那麼簡單,還有很多東西需要研究。

總結:as2的事件分發機制是 從上根容器一直往下找 找到了可以響應事件的容器就停止 然後觸發事件響應。

  as3分為兩個過程  先從上根容器一直往下找 找到最底層的控件,然後依次向上觸發事件