Przechwytywanie i propagowanie zdarzeń umożliwia ograniczenie korzystania z procedur obsługi zdarzeń.
Koncepcja przechwytywania i propagowania zdarzeń została zapoczątkowana w modelu zdarzeń zastosowanym w języku ActionScript 3.0. Wykorzystanie propagacji zdarzenia umożliwia zoptymalizowanie wykonania kodu ActionScript. W celu zwiększenia wydajności można zarejestrować procedurę obsługi zdarzenia w jednym obiekcie zamiast w wielu obiektach.
Przykład: wyobraźmy sobie tworzenie gry, w której użytkownik musi jak najszybciej klikać jabłka, które w ten sposób są niszczone. Gra usuwa z ekranu każde kliknięte jabłko i dodaje punkty do punktacji użytkownika. Czyha pokusa, aby w celu wykrycia zdarzenia
MouseEvent.CLICK
wywoływanego przez każde jabłko napisać następujący kod:
const MAX_NUM:int = 10;
var sceneWidth:int = stage.stageWidth;
var sceneHeight:int = stage.stageHeight;
var currentApple:InteractiveObject;
var currentAppleClicked:InteractiveObject;
for ( var i:int = 0; i< MAX_NUM; i++ )
{
currentApple = new Apple();
currentApple.x = Math.random()*sceneWidth;
currentApple.y = Math.random()*sceneHeight;
addChild ( currentApple );
// Listen to the MouseEvent.CLICK event
currentApple.addEventListener ( MouseEvent.CLICK, onAppleClick );
}
function onAppleClick ( e:MouseEvent ):void
{
currentAppleClicked = e.currentTarget as InteractiveObject;
currentAppleClicked.removeEventListener(MouseEvent.CLICK, onAppleClick );
removeChild ( currentAppleClicked );
}
Kod wywołuje metodę
addEventListener()
dla każdej instancji Apple. Usuwa również każdy detektor po kliknięciu jabłka, stosując w tym celu metodę
removeEventListener()
. Jednak model zdarzenia w języku ActionScript 3.0 udostępnia fazę przechwytywania i propagacji dla niektórych zdarzeń, dzięki czemu można je wykrywać z nadrzędnego obiektu InteractiveObject. W rezultacie - możliwe jest zoptymalizowanie powyższego kodu i zminimalizowanie liczy wywołań metod
addEventListener()
i
removeEventListener()
. Poniższy kod korzysta z fazy przechwytywania w celu wykrywania zdarzeń z obiektu nadrzędnego:
const MAX_NUM:int = 10;
var sceneWidth:int = stage.stageWidth;
var sceneHeight:int = stage.stageHeight;
var currentApple:InteractiveObject;
var currentAppleClicked:InteractiveObject;
var container:Sprite = new Sprite();
addChild ( container );
// Listen to the MouseEvent.CLICK on the apple's parent
// Passing true as third parameter catches the event during its capture phase
container.addEventListener ( MouseEvent.CLICK, onAppleClick, true );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
currentApple = new Apple();
currentApple.x = Math.random()*sceneWidth;
currentApple.y = Math.random()*sceneHeight;
container.addChild ( currentApple );
}
function onAppleClick ( e:MouseEvent ):void
{
currentAppleClicked = e.target as InteractiveObject;
container.removeChild ( currentAppleClicked );
}
Kod został uproszczony i znacznie zoptymalizowany. Zawiera również tylko jedno wywołanie metody
addEventListener()
w kontenerze nadrzędnym. Detektory nie są już rejestrowane w instancjach Apple, więc nie muszą być usuwane po kliknięciu jabłka. Moduł obsługi
onAppleClick()
może zostać dodatkowo zoptymalizowany poprzez zatrzymanie propagacji zdarzenia:
function onAppleClick ( e:MouseEvent ):void
{
e.stopPropagation();
currentAppleClicked = e.target as InteractiveObject;
container.removeChild ( currentAppleClicked );
}
Faza propagacji może zostać wykorzystana do przechwycenia zdarzenia poprzez przekazanie
false
jako trzeciego parametru do metody
addEventListener()
:
// Listen to the MouseEvent.CLICK on apple's parent
// Passing false as third parameter catches the event during its bubbling phase
container.addEventListener ( MouseEvent.CLICK, onAppleClick, false );
Domyślną wartością dla parametru fazy przechwytywania jest
false
, więc można go pominąć:
container.addEventListener ( MouseEvent.CLICK, onAppleClick );