Capture et propagation d’événement

La capture et la propagation d’événement permettent de réduire le nombre de gestionnaires d’événement.

Le modèle d’événement d’ActionScript 3.0 a introduit les concepts de capture et de propagation d’événement. En propageant un événement, vous pouvez optimiser le temps d’exécution du code ActionScript. Vous pouvez enregistrer un gestionnaire d’événement sur un objet, plutôt que sur plusieurs objets, pour améliorer les performances.

Imaginons, par exemple, un jeu dans lequel l’utilisateur doit cliquer sur des pommes aussi vite que possible pour les détruire. Chaque pomme sur laquelle clique l’utilisateur est effacée et des points sont ajoutés au score de celui-ci. Pour écouter l’événement MouseEvent.CLICK distribué par chaque pomme, vous pourriez être tenté de rédiger le code suivant :

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

Le code appelle la méthode addEventListener() sur chaque occurrence d’Apple. Il supprime également chaque écouteur lorsque l’utilisateur clique sur une pomme, à l’aide de la méthode removeEventListener() . Cependant, le modèle d’événement d’ActionScript 3.0 propose une phase de capture et de propagation de certains événements, vous permettant d’écouter ceux-ci à partir d’un objet interactif (InteractiveObject) parent. Il est donc possible d’optimiser le code ci-dessus et de réduire le nombre d’appels des méthodes addEventListener() et removeEventListener() . Le code suivant utilise la phase de capture pour écouter les événements en provenance de l’objet parent :

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

Le code est simplifié et grandement optimisé ; il appelle la méthode addEventListener() une seule fois sur le conteneur parent. Les écouteurs n’étant plus enregistrés sur les occurrences d’Apple, il est inutile de les supprimer lorsque l’utilisateur clique sur une pomme. Il est possible d’optimiser encore plus le gestionnaire onAppleClick() , en arrêtant la propagation de l’événement, ce qui l’empêche d’aller plus loin :

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

Vous pouvez aussi utiliser la phase de propagation pour capturer l’événement en transmettant la valeur false en tant que troisième paramètre à la méthode 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 );

La valeur par défaut du paramètre de la phase de capture est false ; vous pouvez donc l’omettre :

container.addEventListener ( MouseEvent.CLICK, onAppleClick );