Захват событий и цепочки событий

Захват и цепочки событий позволяют уменьшить количество обработчиков событий.

В модели события ActionScript 3.0 представлены такие принципы, как захват событий и цепочки событий. Цепочки событий позволяют быстрее выполнять код ActionScript. Обработчик событий можно зарегистрировать не для нескольких объектов, а всего для одного, что ускорит обработку.

Представим, что разработчик пишет код для игры, в которой нужно как можно скорее собирать яблоки щелчком мыши. При каждом щелчке яблоко исчезает, а игроку добавляются очки. Для прослушивания события MouseEvent.CLICK , отправляемого каждым яблоком, разработчик может написать следующий код.

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

Для каждого экземпляра Apple вызывается код addEventListener() . Когда игрок щелкает по яблоку, с помощью метода removeEventListener() также удаляется каждый прослушиватель. Однако в ActionScript 3.0 есть возможность создавать захваты и цепочки событий, чтобы прослушивать их с помощью родительских интерактивных объектов (InteractiveObject). Это позволяет оптимизировать показанный выше код и свести к минимуму вызовы методов addEventListener() и removeEventListener() . В следующем коде для прослушивания событий с родительского объекта используется фаза захвата.

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

Как видим, этот код проще и гораздо лучше оптимизирован. Метод addEventListener() вызывается лишь единожды на родительском контейнере. Прослушиватели больше не связаны с экземплярами Apple, поэтому их не нужно удалять каждый раз при щелчке по яблоку. Обработчик onAppleClick() можно оптимизировать и далее. Для этого нужно остановить распространение события.

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

Фазу захвата можно также использовать для перехвата события. Для этого нужно передать методу addEventListener() значение false в качестве третьего параметра.

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

Значение параметра фазы захвата по умолчанию — false , поэтому его можно не указывать.

container.addEventListener ( MouseEvent.CLICK, onAppleClick );