Cattura e bubbling degli eventi

Utilizzate la cattura e il bubbling degli eventi per ridurre l'uso dei gestori di eventi.

Il modello di eventi di ActionScript 3.0 ha introdotto i concetti di cattura e bubbling degli eventi. Sfruttando correttamente il bubbling di un evento è possibile ottimizzare i tempi di esecuzione del codice ActionScript. Potete registrare un gestore di eventi in un solo oggetto anziché in più oggetti, ottenendo un miglioramento delle prestazioni.

Per esempio, immaginate di creare un videogioco in cui l'utente deve fare clic su delle mele il più velocemente possibile per distruggerle. Ogni volta che si fa clic su una mela, questa viene rimossa dallo schermo e vengono aggiunti dei punti al punteggio dell'utente. Per intercettare l'evento MouseEvent.CLICK inviato da ogni mela, potreste essere tentati di scrivere il codice seguente:

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

Il codice chiama il metodo addEventListener() su ogni istanza Apple. Inoltre rimuove ogni listener quando viene fatto clic su una mela, utilizzando il metodo removeEventListener() . Tuttavia, nel modello di eventi di ActionScript 3.0 sono disponibili le fasi di cattura e di bubbling per alcuni eventi, quindi è possibile intercettarli tramite un InteractiveObject principale. Di conseguenza, è possibile ottimizzare il codice precedente e ridurre al minimo il numero di chiamate ai metodi addEventListener() e removeEventListener() . Il codice seguente usa la fase di cattura per intercettare gli eventi dell'oggetto principale:

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

Questo codice è più semplice e molto più ottimizzato, poiché contiene una singola chiamata al metodo addEventListener() sul contenitore principale. I listener non vengono più registrati nelle istanze Apple, quindi non è necessario rimuoverli quando viene fatto clic su una mela. Il gestore onAppleClick() può essere ulteriormente ottimizzato interrompendo la propagazione dell'evento:

function onAppleClick ( e:MouseEvent ):void 
{ 
    e.stopPropagation(); 
    currentAppleClicked = e.target as InteractiveObject; 
    container.removeChild ( currentAppleClicked ); 
}

È anche possibile utilizzare la fase di bubbling per intercettare l'evento, passando false come terzo parametro al metodo 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 );

Il valore predefinito per il parametro della fase di cattura è false , quindi potete ometterlo:

container.addEventListener ( MouseEvent.CLICK, onAppleClick );