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