addEventListener大研究の巻その2【flash as3.0】
さて、前回中途半端で終わってしまったaddEventListener。今回はもうちょっと掘り進めてみましょう。
第3引数のuseCaptureをtrueにするとイベントをキャプチャ段階で処理できますよー的なところで終わっていたと思います。
今回は、前回の復習からその具体例までいってみましょう!
●復習!
・表示リスト上のオブジェクトへのイベント登録は親オブジェクトにするだけでよい
A上にB、Cといったスプライトを配置し、AやBやCがクリックされた場合のイベント処理をする場合、それぞれにaddEventListenerする必要はありません。
AにさえすればOKです。
具体例
この例ではAにのみaddEventListenerして、イベント処理時に実行する関数の中で「何がクリックされたか」によって処理を分岐しています。
これによる一番のメリットは「removeEventListenerし忘れを防げる」というところだと思います。
オブジェクトを削除するときremoveEventListenerし忘れたまま削除すると、オブジェクトへの参照が残ってメモリが圧迫される原因になります。
他にも「登録しているイベントが多くてわけがわからなくなる」という事態も防げそうです。
・イベント処理には3段階のプロセス(キャプチャ、ターゲット、バブリング)があり、バブリング段階で処理される。
まずイベントのトリガーが引かれた時点で、リスナー登録したオブジェクトから子オブジェクトに通知が行くのがキャプチャフェーズ(段階)。
イベントの対象オブジェクトまで通知がいくとターゲットフェーズに移り、その後その対象オブジェクトから、リスナー登録された大元の親オブジェクトまで通知がさかのぼります。
これがバブリングフェーズです。
処理はバブリングフェーズに行われますが、第3引数(useCapture:Boolean)をtrueにするとキャプチャフェーズで処理が行われます。
キャプチャフェーズでの処理は若干重いです。。。
さて、前回はここまでやりました。
今回は早速、キャプチャフェーズでのイベント処理をやってみようかと思います。
●実際にuseCapture = trueにしてみる
先ほどの実行例の中で、画面右上の「useCapture = false(デフォルト)」というところをクリックすることで、第3引数がtrueの場合とfalseの場合の挙動を試せるようになっています。
trueに切り替えると、リスナー登録しているA自身をクリックしても何も起きないかと思います。
これは、それ自身をクリックした場合、キャプチャフェーズを経ずにターゲットフェーズからイベントが始まってしまうので起こる現象です。
また「両方を登録」の場合、useCapture = trueの場合の処理が先に割り込んで行われていることがわかります。
これにより、通常のイベント処理に割り込ませて処理を行うことが可能になります。
●もともとバブリング段階のないイベントもある
例えば、Event.ADDED_TO_STAGEはオブジェクトがステージ上に配置された時点で処理されるイベントですが、バブリングフェーズが存在しません。
これは単純にオブジェクトがステージ上に配置されたことを通知する役割しか果たさないのですが、useCapture = trueにしてみると、例えばTextFieldがステージ上に配置された時点でそのautoSizeプロパティを自動的に"left"にする、といった初期化処理も可能になります。
これは、ステージ上に配置されたオブジェクトがEvent.targetになるからです。
具体的には
stage.addEventListener(Event.ADDED_TO_STAGE,function(event:Event):void{if("autoSize" in event.target)event.target.autoSize = "left";},true)
とします。結構使えるかもしれません。
●まとめ
なんかまだまだ中途半端なエントリーですが、addEventListenerの奥の深さは解っていただけたんじゃないかな、と思います。
機会があればまた取り上げてみようかな?と思います。