[Flex help] Using Events - Event Propagation 공부/developeGuide-Flex help2010. 3. 18. 14:28
Event propagation
*Capturing
*Targeting
*Bubbling
각 단계에서 노드들은 이벤트에 응답할 수 있는 기회를 갖게 된다. VBox 컨테너안의 Button 컨트롤을 유저가 클릭했다고 가정하면, Capturing 단계에서 이벤트를 처리할 listeners에 대해 플렉스는 Application 객체와 그 VBox를 체크한다. 그리고 Target 단계에서 Button의 listeners를 동작시킨다. Bubbling 단계에서는 VBox와 Application 에 이벤트 처리 기회를 다시 주지만 이번에는 Capturing단계의 반대의 순서로 진행된다.
ActionScript3.0에서는 개발자는 이벤트 흐름에 속한 어떤 노드든지 이벤트 리스너를 등록시킬 수 있다. 그러나, 모든 이벤트가 이벤트 흐름의 3단계안에 속한 것은 아니다. 이벤트의 어떤 타입은 타겟노드에 직접적으로 디스패치 시키고 capturing과 bubbling단계에 속하지 않는다. 모든 이벤트는 top노드로 부터 디스패치 된경우외에는 Capturing 단계가 가능하다.
다른 이벤트들은 소켓클래스 인스턴스에 디스패치하는 이벤트 처럼 display list에 없는 객체를 타겟할것이다. 이 이벤트 객체들은 captuing이나 bubbling 단계가 없이 타겟노드를 직접적으로 간다. cancelable 프로퍼티을 true로 설정하면서 이벤트 모델을 통해 흐를때 취소를 할 수 있다.
Capturing과 bubbling은 이벤트 객체가 display list에서 노드에서 노드로 이동할때 발생하는데 이 과정들은 상속과는 아무런 관련이 없다. 오직 컨테이너나 컨트롤같은 visual object인 Display Object 객체만 이런 이벤트 흐름 (3단계)를 가질 수 있다.
Mouse events 와 keyboard events 는 bubble과 관련있다. DisplayObject 객체는 명시적으로 무엇을 하라고 지시하지 않는다면 capturing단계에서 디폴트 형식으로 수행을 하지 않는다.
validator처럼 정체불명의 event dispatcher는 capture나 bubble을 통할 이벤트 객체같은 visual display list가 없기 때문에 오직 targeting 단계만 존재한다.
About the target and currentTarget properties
모든 event객체는 전파 과정에서 어디를 지나는지 알려주는 'target'과 'currentTarget' 프로퍼티를 가지고 있다. target프로퍼티는 이벤트를 발생시킨 이벤트를 가르키고 currentTarget프로퍼티는 이벤트리스너를 확인하고 있는 현재 노드를 가르킨다.
어떤 컴포넌트에 리스너를 적어 MouseEvent.CLICK같은 마우스 이벤트를 처리할 때 event.target프로퍼티는 컴포넌트를 참조할 필요가 없다.
Capturing phase
Flex는 어떤것이 해당 이벤트의 리스너로 등록되었는지 확인하기 위해 display list에서 이벤트의 조상들을 체크한다. flex는 root 부터 target객체의 바로 위의 부모까지 이동한다. 대부분의 경우 root는 Stage이고 그 밑으로 Systemmanager, 그 밑으로 Application객체가 있다.
예를 들어, 다음과 같이 어플리케이션안에 버튼을 포함한 타이틀 위도우를 가진 패널이 있다고 가정하면,
Panel
TitleWindow
Button
리스너가 만약 Button 컨트롤의 click event에 있다면, Capturing단계동안은 다음 과정이 발생한다.
1. Application 에서 click event 리스너에 대해 체크한다.
2. Panel 에서 click event 리스너에 대해 체크한다.
3. TitleWindow 에서 click event 리스너에 대해 체크한다.
capturing 단계에서 flex는 어떤 노드에서 리스너를 호출시켰는지 매칭시키기 위해 Event 객체에서 currentTarget 프로퍼티의 값을 바꾼다. Target프로퍼티는 계속 이벤트가 발생된 객체만을 가르킨다.
capturing단계는 디폴트가 없으며, use_capture 아규먼트는 디폴트 값으로 false를 가진다. capturing 단계에서 리스너를 추가 하는 방법은 아래 예와 같이 use_capture 아규먼트를 true로 addEventListener()를 호출하는 방법이 있다.
myPanel.addEventListener(MouseEvent.MOUSE_DOWN, clickHandler, true);
MXML에 이벤트 리스너를 inline할 경우 디폴트인 false값을 갖는다. (오버라이드 할 수 없다.)
use_cature를 true로 설정하면 (capturing단계를 통해 이벤트를 전달한다면) capturing단계의 리스너는 반응하지 않지만 bubbling단계는 여전히 이벤트가 리스너를 체크한다. 만약 이벤트가 capturing과 bubbling을 둘 사이를 횡단하길 원한다면 addEventListener()를 두번 호출해야만한다.한번은 true로 한번은 false로...
capturing단계는 잘 사용되지 않으며 bubbling단계가 더 많이 이용된다.
Targeting phase
flex는 이 단계에서 이벤트 디스패처의 리스너를 호출한다. 또한 Display list의 다른 노드들은 이벤트 리스너에 대한 체크를 하지 않으며 currentTarget과 target프로퍼티의 값이 같다.
Bubbling phase
flex는 이벤트 리스너에 대해 이벤트의 조상을 체크한다. capturing단계와 반대로 타겟 객체의 바로 윗 객체부터 root 객체까지 올라가며 체크를 한다. Mouse event와 keyboard event는 bubble에 속해있는데 bubble에 high-level 이벤트가 디스패치되는것은 흔한일이아니다. bubble될 수 있는 이벤트는 change, click, doubleClick, keyDown, keyUp, mouseDown, mouseUp이 있다. 이벤트를 bubble할지 말지 결정하기 위해서는, Adobe Flex Language Reference의 event를 참고한다.
bubbling단계 동안에 flex는 currentTarget 프로퍼티의 값을 노드를 이동하며 바꿔주고 Target프로퍼티는 계속 이벤트를 발생시킨 객체를 가르킨다.
flex가 이벤트 리스너를 호출할때 그 이벤트 객체는 실질적으로 display list에서 더 깊은 객체에 의해 보내질 것이다. 이벤트를 실제로 발생시키는 객체는 target이고, 그 이벤트가 현재 버블링 되는 객체는 currentTarget이다. 그러므로 일반적으로 이벤트 리스너에서 현재 객체를 참조할 때는 target프로퍼티 보다 currentTarget프로퍼티를 사용해야한다.
어떤객체가 이벤트를 발생시키는 객체일경우만 객체에 이벤트 리스너를 등록할 수 있다. 예를 들어, Form 컨테이너가 Button 컨트롤을 포함하고 있을지라도, Form 컨테이너는 click event를 보내지 않기 때문에 click event를 listen하기 위해 Form 컨테이너를 등록할 수 없다. Form 컨테이너는 mouseDown event 를 보내기 때문에 form 컨테이너 태그에 mouseDown event를 지정함으로서 이벤트 리스너가 언제든지 Button컨트롤이나 Form 컨테이너가 mouseDown event를 받을 수 있도록 동작시킨다.
만약 useCapture프로퍼티를 true로 설정하면 (이벤트가 capturing을 통해 propagation 하면) 디폴트 버블링 수행에 대해 버블하지 않는다. 만약 이벤트가 capturing과 bubbling을 둘 사이를 횡단하길 원한다면 addEventListener()를 두번 호출해야만한다.한번은 true로 한번은 false로...
capturing단계는 잘 사용되지 않으며 bubbling단계가 더 많이 이용된다.
이벤트는 오직 display list에서 타겟 객체의 윗단계로 거슬러 올라간다. 같은 컨테이너 안의 두 Button 컨트롤 사이에서 서로의 이벤트를 가로막지 않는다.
Detecting the event phase
이벤트 객체의 eventPhase프로퍼티를 통해 어떤단계에 있는지 확인할 수있다. 이 프로퍼티는 integer타입으로 정의되어져있다.
* 1 = Capturing phase (CAPTURING_PHASE)
* 2 = Targeting phase (AT_TARGET)
* 3 = Bubbling phase (BUBBLING_PHASE)
<?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>
결과화면
Stopping propagation
어떤 단계에서든 다음의 함수를 통해 display list의 이벤트 이동을 멈출 수 있다.
stopPropagation()
stopImmediatePropagation()
두함수는 비슷하지만 현재 노드에서 수행하려는 이벤트 리스너를 제외한 다른 이벤트 리스너를 수행할지 안할지 결정하는 부분에서 차이점이 있다. 두함수 모두 이벤트 객체가 다음 노드로 이동하는 것을 멈추지만,
stopPropagation()함수는 현재 노드에서 다른 이벤트 리스너를 수행하는것을 허락한다. 반면에,
stopImmediatePropagation()함수는 현재 노드에서 다른 이벤트 리스너를 수행하는것을 허락하지 않는다.
다음 예에서 Panel 컨테이너 안에 TitleWindow 컨테이너가 있는데 두 컨테이너 모두 mouseDown event에 반응한다. 결과적으로, 만약에 stopImmediatePropagation()함수가 호출되지 않으면 두번의 showAlert()함수가 호출되게 된다.
<!-- 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>
[플렉스 help 영문 정리]
원본: http://livedocs.adobe.com/flex/3/html/events_08.html#203937
'공부 > developeGuide-Flex help' 카테고리의 다른 글
[Flex help] Using the StyleManager class (0) | 2010.03.30 |
---|---|
[Flex help] Using Events - About keyboard events (0) | 2010.03.19 |
[Flex help] Using Events - Using event subclasses (0) | 2010.03.19 |
[Flex help] Using Events - Event priorities (0) | 2010.03.19 |
[Flex help] Using Events - About Event (0) | 2010.03.18 |