イベントフェーズとは、イベントがトリガされた時にイベントリスナーが存在するかを確認する順番(段階)のことで、次の3段階構成になっています。
[ キャプチャ段階 ] → [ ターゲット段階 ] → [ バブリング段階 ]
●キャプチャ段階
イベントが発行されたターゲットの祖先の表示リストを親側から順に検査し、リスナーが登録されているかを確認します。
●ターゲット段階
イベントが発行されたターゲットのリスナーが呼び出されます。
●バブリング段階
イベントが発行されたターゲットの祖先の表示リストをターゲット側から順に検査し、リスナーが登録されているかを確認します。
今回の その1 ではターゲット段階とバブリング段階に着目し、サンプルソースを通してイベントフェーズを確認していきます。
以下のサンプルソースは、入れ子構造の3つのVBox (外側から outerBox - middleBox - innerBox という id を付加) を用意し、ApplicationのcreationCompleteイベント処理で各々のVBoxにクリックイベントのリスナーを発行します。
サンプルソースを実行し何れかのVBoxをクリックすると、クリックイベントの処理として
「 "リスナー処理対象VBoxのid":"処理連番"["イベントフェーズ段階"] 」
が右側にリスト表示されます。 わかりやすい様に文字色はVBoxの背景色と同色にセットしています。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="horizontal" horizontalAlign="center" backgroundColor="#FFFFFF"
creationComplete="onCreationComplete()" >
<mx:Script>
<![CDATA[
import mx.controls.Label;
private var counter:int = 1;
private function onCreationComplete():void{
innerBox.addEventListener(MouseEvent.CLICK, onCatchDispatcher);
middleBox.addEventListener(MouseEvent.CLICK, onCatchDispatcher);
outerBox.addEventListener(MouseEvent.CLICK, onCatchDispatcher);
}
private function onCatchDispatcher(e:MouseEvent):void{
var lbl:Label = new Label();
var phase:String = getPhase(e.eventPhase);
lbl.text = counter + " : " + e.currentTarget.id + " [" + phase + "]";
setLabelColor(lbl, e.currentTarget.id);
eventList.addChild(lbl);
counter++;
}
private function getPhase(eventPhase:int):String{
var phase:String;
//EventPhase 1=キャプチャ段階, 2=ターゲット段階, 3=バブリング段階
switch(eventPhase){
case 1:
phase = "キャプチャ段階";
break;
case 2:
phase = "ターゲット段階";
break;
case 3:
phase = "バブリング段階";
break;
}
return phase;
}
private function setLabelColor(lbl:Label, targetBox:String):void{
if(targetBox == "innerBox"){
lbl.setStyle("color", "#CC0000");
}else if(targetBox == "middleBox"){
lbl.setStyle("color", "#00CC00");
}else if(targetBox == "outerBox"){
lbl.setStyle("color", "#0000CC");
}
}
]]>
</mx:Script>
<mx:HBox>
<mx:VBox id="outerBox" minHeight="150" minWidth="150" horizontalAlign="center" verticalAlign="middle" backgroundColor="#0000CC">
<mx:VBox id="middleBox" minHeight="100" minWidth="100" horizontalAlign="center" verticalAlign="middle" backgroundColor="#00CC00">
<mx:VBox id="innerBox" minHeight="50" minWidth="50" horizontalAlign="center" verticalAlign="middle" backgroundColor="#CC0000" />
</mx:VBox>
</mx:VBox>
<mx:VBox id="eventList" fontWeight="bold" />
</mx:HBox>
</mx:Application>
【サンプルソースの実行】
① 一番内側の innerBox (赤色) を1回クリック
② 次に内側の middleBox (緑色) を1回クリック
③ 一番外側の outerBox (青色) を1回クリック
上記①~③の手順で実行した際の結果はこうなりました。
手順①では一番内側のコンポーネントがクリックされたことにより、ターゲット段階として innerBox がリスナーが実行されます。その後、親コンポーネントへの伝播が働くことにより、バブリング段階として middleBox・outerBox の順にリスナーが実行されます。
手順②では middleBox がクリックされたので ターゲット段階として middleBoxのリスナーが実行され、バブリング段階として 親コンポーネントである outerBox のリスナーが実行されます。
手順③では、一番外側のコンポーネントのouterBox がクリックされたので、バブリング段階対象のコンポーネントは存在せず、ターゲット段階の outerBox のリスナーのみ実行されます。
つまり、イベント発行したコンポーネントはターゲット段階としてリスナーを実行し、イベント発行したコンポーネントよりも親のコンポーネントはバブリング段階としてリスナーを実行しています。
考え方はシンプルですが、1つのアクション(イベント)で複数個所のリスナーを動かせる非常に強力なしくみですよね。
次回は、キャプチャ段階についてサンプルソースを見ながら確認したいと思います。