Przechwytywanie i propagowanie zdarzeń

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 );