イベントフェーズとは、イベントがトリガされた時にイベントリスナーが存在するかを確認する順番(段階)のことで、次の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つのアクション(イベント)で複数個所のリスナーを動かせる非常に強力なしくみですよね。
次回は、キャプチャ段階についてサンプルソースを見ながら確認したいと思います。