1.     目标匹配阶段 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

在目标匹配阶段,Flex调用事件调度者的监听器,Event对象的currentTargettarget属性的值将是相同的。

 

2.     冒泡阶段

在冒泡阶段,Flex会在事件的祖先(event’s ancestors)中查找事件监听器。Flex将从事件调度者的直接祖先开始向上查找,知道根祖先。这与捕获阶段相反。

 

例如,如果你的程序有一个Panel容器,Panel容器包含一个TitleWindow容器,TitleWindow容器又包含一个按钮控件,那么程序的结构如下所示:

 

 

Application

           Panel

                    TitleWindow

                             Button

 

如果你监听按钮控件的点击事件,如果允许冒泡的话,下面的步骤将在冒泡阶段发生:

 

(1)     检查TitleWindow容器上是否有点击事件监听器;

(2)     检查Panel容器上是否有点击事件监听器;

(3)     检查Application容器上是否有点击事件监听器。

 

只有在bubbles属性被设定为true时,事件才会冒泡。鼠标事件和键盘事件是冒泡的。可以冒泡的事件包括change,click,doubleClick,keyDown,keyUp,mouseDownmouseUp

 

Flex调用一个事件监听器时,Event对象可能实际上是被一个显示列表中的深层对象调度。最先调度事件的对象是Event对象的target属性。当前正在冒泡的对象是Event对象的currentTarget对象。所以,当你要引用事件监听器的当前对象时,必须总是使用currentTarget属性而不是target属性。

 

只有当对象调度事件的时候,你才能为那个对象添加事件监听器。例如,你不能让一个Form容器监听click事件,除非那个容器包含有一个按钮控件。Form容器本身不能调度点击事件。Form容器可以调度mouseDown事件,所以你可以在Form容器上添加moseDown事件监听器。如果你那样做了,每当按钮被点击或者Form容器受到了一个mouseDown事件的时候,你的事件监听器会被调用。

 

如果你将useCapture属性设置为true,也就是说,如果一个事件在捕获阶段被传播,那么,它将不会冒泡,而不管它默认的冒泡行为。如果你希望你的事件能够同时在捕获阶段和冒泡阶段被传播,你必须调用addEventListener()方法两次:一次将useCapture参数设定为true,另一次将useCapture参数设定为false

 

事件只能在显示列表中的祖先链中冒泡。处于同一容器中的两个按钮组件不会拦截对方的事件。

        

3.     探测事件阶段

你可以通过使用Event对象的eventPhase属性来探查你正在使用哪个阶段。这个属性包含了一个整数。内容描述如下所示:

 

1:捕获阶段(CAPTURE_PHASE)

2:目标匹配阶段(AT_TARGET)

3:冒泡阶段(BUBBLING_PHASE)

 

下面的例子展示了当前阶段和当前目标的ID

 

<?xml version="1.0"?>

<!-- events/DisplayCurrentTargetInfo.mxml -->

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script><![CDATA[

import mx.controls.Alert;

private function showInfo(e:MouseEvent):void {

Alert.show("Phase: " + e.eventPhase + "\n" +

"Current Target: " + e.currentTarget.id);

}

]]></mx:Script>

<mx:Button id="b1"

label="Click Me"

click="showInfo(event)"

/>

</mx:Application>

 

4.     停止传播

在任何阶段,你都可以通过调用下面的方法来组织事件在显示列表中的移动(traversal)

 

stopPropagation()

stopImmediatePropagation()

 

你可以通过调用Event对象的stopPropagation()方法和stopImmediatePropagation()方法来阻止Event对象在事件流的路径中继续运行。两者基本相同,不同之处在于当前节点遗留的事件监听器是否允许被调用。stopPropagation()方法只是在当前节点的所有事件监听器被调用后,阻止事件继续向下个节点传递。stopImmediatePropagation()方法同样会组织Event对象向下个节点传递,但是它也不允许当前节点的任何其他事件监听器被执行。

 

下面的例子创建了一个Panel容器,包含有一个TitleWSindow容器。两个容器都被注册了mouseDown事件监听器。如果你在TitleWindow容器中点击鼠标,showAlert()方法将被调用两次,除非你调用stopImmediatePropagation()方法。如下所示:

 

<?xml version="1.0"?>

<!-- events/StoppingPropagation.mxml -->

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" initialize="init(event);">

<mx:Script><![CDATA[

import mx.controls.Alert;

import flash.events.MouseEvent;

import flash.events.Event;

public function init(e:Event):void {

p1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);

tw1.addEventListener(MouseEvent.MOUSE_DOWN, showAlert);

tw1.addEventListener(Event.CLOSE, closeWindow);

p2.addEventListener(MouseEvent.MOUSE_DOWN,

showAlertWithoutStoppingPropagation);

tw2.addEventListener(MouseEvent.MOUSE_DOWN,

showAlertWithoutStoppingPropagation);

tw2.addEventListener(Event.CLOSE, closeWindow);

}

public function showAlert(e:Event):void {

Alert.show("Alert!\n" + "Current Target: " + e.currentTarget + "\n" +

"Phase: " + e.eventPhase);

e.stopImmediatePropagation();

}

public function showAlertWithoutStoppingPropagation(e:Event):void {

Alert.show("Alert!\n" + "Current Target: " + e.currentTarget + "\n" +

"Phase: " + e.eventPhase);

}

public function closeWindow(e:Event):void {

p1.removeChild(tw1);

}

]]></mx:Script>

<mx:Panel id="p1" title="Stops Propagation">

<mx:TitleWindow id="tw1"

width="300"

height="100"

showCloseButton="true"

title="Title Window 1"

>

 

<mx:Button label="Click Me"/>

<mx:TextArea id="ta1"/>

</mx:TitleWindow>

</mx:Panel>

<mx:Panel id="p2" title="Does Not Stop Propagation">

<mx:TitleWindow id="tw2"

width="300"

height="100"

showCloseButton="true"

title="Title Window 2"

>

 

<mx:Button label="Click Me"/>

<mx:TextArea id="ta2"/>

</mx:TitleWindow>

</mx:Panel>

</mx:Application>