Propagación y captura de eventos

Utilice la propagación y captura de eventos para reducir los controladores de eventos.

El modelo de eventos de ActionScript 3.0 introdujo los conceptos de propagación y captura de eventos. El aprovechamiento de la propagación de un evento puede ayudar a optimizar el tiempo de ejecución de código ActionScript. Con el fin de mejorar el rendimiento, es posible registrar un controlador de eventos en un objeto, en lugar de en varios objetos.

Como ejemplo, imagine la creación un juego en el que el usuario debe hacer clic en manzanas lo más rápido posible para destruirlas. El juego elimina cada manzana de pantalla cuando se hace clic en la misma y añade puntos a la puntuación del usuario. Para detectar el evento MouseEvent.CLICK distribuido por cada manzana, se puede tender a escribir el siguiente código:

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

El código llama al método addEventListener() en cada instancia de Apple. También se elimina cada detector de evento cuando se hace clic en una manzana, utilizando el método removeEventListener() . Sin embargo, el modelo de eventos de ActionScript 3.0 proporciona una fase de propagación y captura para algunos eventos, lo que permite detectarlos desde un objeto InteractiveObject principal. Como resultado, es posible optimizar el código anterior y reducir el número de llamadas a los métodos addEventListener() y removeEventListener() . El siguiente código utiliza la fase de captura para detectar los eventos del objeto principal:

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

El código se simplifica y se optimiza mucho más, con sólo una llamada al método addEventListener() en el contenedor principal. Los detectores no vuelven a registrarse en las instancias de Apple, por lo que no es necesario eliminarlos cuando se hace clic en una manzana. El controlador onAppleClick() puede optimizarse más, deteniendo la propagación del evento, lo que evita que éste vaya más allá:

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

La fase de propagación también se puede utilizar para capturar el evento, transmitiendo false como tercer parámetro al método 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 );

El valor predeterminado para el parámetro de fase de captura es false , por lo que puede omitirlo:

container.addEventListener ( MouseEvent.CLICK, onAppleClick );