| « Отлов событий из Item Renderer'ов | Вторая встреча RAFPUG в рамках Adobe Flex and AIR Pre-Release Tour » |
Еще о событиях в ActionScript

Если кто-то помнит, на первой встрече Русскоязычной Группы Пользователей Flash-платформы (RAFPUG) я рассказывал о событиях в ActionScript 3. Как краевед могу сказать, что тема событий в ActionScript далеко не так тривиальна, как это может показаться на первый, второй и третий взгляд. Работая с ними довольно долго, можно тем не менее иногда обнаружить что-то новое, сделать новые выводы и найти применения старым вещам. В частности, в том докладе я сказал некоторую лажу и во всем зале меня никто не поправил
Поправлю себя сам.
Там я сказал, что event flow (поток событий) работает только для визуальных объектов и только для интерактивных событий мыши и клавиатуры, генерируемых Flash-плеером. На основании этого я продемонстрировал пример с искусственным бабблингом (фазой пузырька). И сделал слегка неверные выводы.
На самом деле, на практике все гораздо проще. И мой тот пример вполне работоспособный, но более актуальный для невизуальных объектов, либо для того, чтобы объекты генерировали целевую фазу (target phase) и фазу пузырька (bubbling phase) одновременно. Речь идет о делегировании события.
Для простой же фазы пузырька в визуальных объектах практически ничего не надо, и сейчас я это проиллюстрирую.
В изначальном утверждении про визуальные объекты и поток событий все правильно если рассматривать под потоком событий все три фазы (capture, target и bubbling). Но фаза пузырька (bubbling) работает и так, сама по себе.
Рассмотрим пример:
Пример сделан в виде просто AS-проекта для наглядности. Исходники можно посмотреть тут. Скачать проект можно тут.
Что мы видим на данном примере. Есть корневой Sprite, в котором лежит простой компонент ParentSprite (внешний серый квадрат), в нем лежит компонент ChildSprite, при клике на внутренний квадрат которого наш компонент генерит событие, которое ловится внешним Sprite‘ом безо всякого участия ParentSprite:
- private function onInsideChildClick (event:MouseEvent):void
- {
- dispatchEvent(new Event ("ourTargetEvent", true));
- }
Обработка события видна в текстовом поле. Весь секрет в волшебных пузырьках во втором параметре конструктора класса Event (он установлен в true). Это и есть бабблинг. И ParentSprite автоматом бабблит его. Безо всякого кода.
Естественно, это просто иллюстрация. В реальности неплохо бы сделать кастомный класс события, соответствующие константы итд.
Гарантирую, что это может сильно облегчить вам жизнь.
Трекбек адрес этой записи
URL трекбека (щелкните правой кнопкой мыши и скопируйте ссылку)
12 комментариев
Костя, наверное и сами разработчики Flash Player не знают о пузырьках... то есть о событиях Flash Player всего того, что знаешь о них ты
Можно не заморачиваться на том, откуда (из какого контейнера или контрола) посылается событие, а потому запросто менять вложенность контейнеров.
И точно так же можно подписаться на одно событие одного контейнера, а ловить кучу других от других вложенных контейнеров
Я думаю, что есть смысл подписываться таким обобщенным образом все-таки на какие-то более-менее конкретные события (ClickAddUser), а не просто на клик. Тогда проблем с тем, что произошел отлов какого-то левого события не будет.
После ряда вариантов пришел к такому способу использования: в MVC генерю события своего класса ViewEvent, с баблингом. Если на каком-то этапе (например в корне компонента) считаю, что событие дальше никому не нужно слать, просто делаю stopPropagation()
Дошедшие события отлавливаю в классе Main, отдаю на обработку в контроллер (а иногда Main делаю контроллером) и дальше рассылаются уже события контроллера, на которые подписываю Model и View.
В итоге получается очень симпатичная архитектура.
Еще раз спасибо за доклад.
в MVC в элементах View генерю события своего класса ViewEvent, с баблингом.
Не в тему: в Cairngorm есть странная особенность - имена команд должны быть уникальными:
addCommand( LoginEvent.EVENT_LOGIN, LoginCommand );
addCommand( LogoutEvent.EVENT_LOGOUT, LogoutCommand );Т.е. если у вас в различных классах кастомных событий одинаковые значения констант-событий
(SiteLoginEvent.EVENT_LOGIN == MessengerLoginEvent.EVENT_LOGIN) то диспатчер-синглтон расскажет вам про эту "ошибку" еще на стадии добавления команд через addCommand. Получается, нужно как в C писать различные префиксы типа public static const EVENT_LOGIN = "SITE_LOGIN_EVENT_EVENT_LOGIN"; В принципе, механизм глобального диспатчера и кучи контроллеров меня очень даже устраивает своей универсальностью если бы не это.
Конструктор евента:
GetMeetingOrganizersEvent(){
super(MyController.EVENT_GET_MEETING_ORGANIZERS);
}
В контроллере:
addCommand(MyController.EVENT_GET_MEETING_ORGANIZERS, GetMeetingOrganizersCommand);
Здесь тоже конечно есть нюансы, например непривычно немного, также по первости чтобы узнать тип нужно залезать внутрь евента, но потом привыкаешь просто привыкаешь испольщовать Cairngorm naming convention и лезть сразу в нужный пакет.
Если я правильно понял проблему