改进ActionScript3的事件机制:事件桥EventBridge,加了一些自己的总结

来源:互联网 发布:excel2003数据透视表 编辑:程序博客网 时间:2024/05/12 10:45
告示:本文为原创文章, 如果转载请注明出处!http://summerofthatyear-gmail-com.iteye.com/blog/328259
      在Flex应用中,由于actionscript3的事件机制是在显示对象一层层向上冒泡的,所以如果在比较复杂的页面结构的时候,你可能会被事件的一层层的冒泡搞的晕头转向.而且在底层派发事件,高层侦听事件,也是很麻烦的一件事情.
      有了"事件桥"这一切将不再是问题,事件桥的功能是它可以把一个事件从一个地方传到任意另外一个地方.不需要冒泡!因为他不通过显示对象的父子关系级级散发,而通过一个第三方类来跳转。这样即提高了性能又方便了用户。
      听不懂没关系, 举个例子就一目了然了.
      这个例子很简单, 是一个选择用户的模块, 就是一个TextArea和一个Button, 点击Button弹出一个TitleWindow(PopUpManager). TitleWindow有一个DataGrid, 然后在DataGrid里面选择一个用户返回;
      首先是一个用户对象:
Java代码  收藏代码
  1. package com.montage.vo  
  2. {  
  3.     /** 
  4.      * @author Montage 
  5.      */   
  6.     public class User  
  7.     {  
  8.         public function User()  
  9.         {  
  10.         }  
  11.           
  12.         public var name:String;  
  13.         public var country:String;  
  14.   
  15.     }  
  16. }  


选择完了用户, 所需要的事件
Java代码  收藏代码
  1. package com.montage.events  
  2. {  
  3.     import com.montage.vo.User;  
  4.       
  5.     import flash.events.Event;  
  6.   
  7.     /** 
  8.      * @author Montage 
  9.      */   
  10.     public class UserEvent extends Event  
  11.     {  
  12.         public static var SELECTED_USER:String = "selectedUser";  
  13.           
  14.         public var user:User;  
  15.           
  16.         public function UserEvent(type:String,  
  17.                                   bubbles:Boolean=false,   
  18.                                   cancelable:Boolean=false)  
  19.         {  
  20.             super(type, bubbles, cancelable);  
  21.         }  
  22.     }  
  23. }  



下面就是“事件桥”,他似乎没有什么代码,就是一个单件类的架子,但是可别小看了它,由于它继承了EventDispatcher所以它可以做到听/发事件!
Java代码  收藏代码
  1. package com.montage.model  
  2. {  
  3.     import flash.events.Event;  
  4.     import flash.events.EventDispatcher;  
  5.       
  6.     //////////////////////  
  7.     //  
  8.     // events  
  9.     //  
  10.     //////////////////////  
  11.     /** 
  12.      * 给当前类注册一个事件 ,注册的作用下面有解释,这里要说明一下name的值,它是自定义事件中的type,类型为String.
  13.      */   
  14.     [Event(name="selectedUser", type="com.montage.events.UserEvent")]  
  15.   
  16.     /** 
  17.      *  
  18.      * @author Montage  
  19.      */   
  20.     public class EventBridge extends EventDispatcher  
  21.     {  
  22.           
  23.         private static var instance:EventMessage = null;  
  24.           
  25.         public function EventMessage()  
  26.         {  
  27.             if( instance != null )  
  28.             {  
  29.                 throw new Error("EventBridge是一个单件类,只能被实例化一次!");  
  30.             }  
  31.         }  
  32.           
  33.         public static function getInstance():EventBridge  
  34.         {  
  35.             if( instance == null )  
  36.             {  
  37.                 instance = new EventBridge();  
  38.             }  
  39.             return instance;  
  40.         }  
  41.     }  
  42. }  


以下是用户列表界面UserList.mxml
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300" title="选择用户">  
  3.     <mx:Script>  
  4.         <![CDATA[ 
  5.             import mx.controls.Alert; 
  6.             import com.montage.events.UserEvent; 
  7.             import com.montage.vo.User; 
  8.             import com.montage.model.EventMessage; 
  9.             import mx.managers.PopUpManager; 
  10.              
  11.             private var eventBridge:EventBridge = EventBridge.getInstance(); 
  12.              
  13.             private function submitHandler():void 
  14.             { 
  15.                 if( grid.selectedIndex > -1 ) 
  16.                 { 
  17.                     var item:XML = XML( grid.selectedItem ); 
  18.                      
  19.                     //创建一个用户 
  20.                     var user:User = new User(); 
  21.                     user.name = item.@name; 
  22.                     user.country = item.@country; 
  23.                      
  24.                     //创建一个UserEvent事件, 把刚刚创建好的user赋给它 
  25.                     var event:UserEvent = new UserEvent( UserEvent.SELECTED_USER ); 
  26.                     event.user = user; 
  27.                      
  28.                     //用EventBridge将这个事件发送出去 
  29.                     eventBridge.dispatch( event ); 
  30.                     cancelHandler(); 
  31.                 } 
  32.                 else 
  33.                 { 
  34.                     Alert.show("请选择一个用户!"); 
  35.                 } 
  36.             } 
  37.              
  38.             private function cancelHandler():void 
  39.             { 
  40.                 PopUpManager.removePopUp( this ); 
  41.             } 
  42.         ]]>  
  43.     </mx:Script>  
  44.     <mx:XML id="users" source="user.xml"/>  
  45.     <mx:DataGrid id="grid" width="100%" height="100%" dataProvider="{users.User}">  
  46.         <mx:columns>  
  47.             <mx:DataGridColumn headerText="姓名" dataField="@name"/>  
  48.             <mx:DataGridColumn headerText="国家" dataField="@country"/>  
  49.         </mx:columns>  
  50.     </mx:DataGrid>  
  51.     <mx:ControlBar width="100%">  
  52.         <mx:Spacer width="100%"/>  
  53.         <mx:Button label="确定" click="submitHandler()"/>  
  54.         <mx:Button label="取消" click="cancelHandler()"/>  
  55.     </mx:ControlBar>  
  56. </mx:TitleWindow>  


用户数据源user.xml
Xml代码  收藏代码
  1. <root>  
  2.     <User name="David" country="America"/>  
  3.     <User name="Tome" country="Canada"/>  
  4.     <User name="Montage" country="China"/>  
  5. </root>  


主界面:
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()" fontSize="12">  
  3.     <mx:Script>  
  4.         <![CDATA[ 
  5.             import com.montage.events.UserEvent; 
  6.             import com.montage.model.EventMessage; 
  7.             import mx.managers.PopUpManager; 
  8.             import com.montage.view.user.UserList; 
  9.              
  10.             private var eventBridge:EventBridge= EventBridge.getInstance(); 
  11.              
  12.             private function init():void 
  13.             { 
  14.                 eventBridge.addEventListener(UserEvent.SELECTED_USER, selectedUserHandler); 
  15.             } 
  16.              
  17.             /** 
  18.              * 选择好以后的反馈 
  19.              */ 
  20.             private function selectedUserHandler( event:UserEvent ):void 
  21.             { 
  22.                 textArea.htmlText = "你选择了:<b>" + event.user.name + "</b>("+ event.user.country +")"; 
  23.             } 
  24.              
  25.             /** 
  26.              * 弹出选择用户的窗口PopUpManager 
  27.              */ 
  28.             private function clickHandler():void 
  29.             { 
  30.                 var userList:UserList = UserList( PopUpManager.createPopUp(this, UserList, true) ); 
  31.                 userList.x = ( width - userList.width ) / 2; 
  32.                 userList.y = ( height - userList.height ) / 2; 
  33.             } 
  34.              
  35.         ]]>  
  36.     </mx:Script>  
  37.     <mx:Panel width="400" height="300" layout="vertical" paddingLeft="5" paddingRight="5" paddingTop="5">  
  38.         <mx:TextArea id="textArea" width="100%"/>  
  39.         <mx:Button label="选择用户" click="clickHandler()"/>  
  40.     </mx:Panel>  
  41. </mx:Application>


这里解释一下,[Event]标签的作用.
[Event]
Event元数据标签用来声明那些被自定义类分派的事件。将这个元数据标签添加到类定义中之后,你就可以在MXML标签中添加事件处理函数来初始化该自定义类。
Custom ButtonLabel class using[Event]
package comps
{
 import mx.controls.Button;
 import flash.events.Event;
 // Define the custom event
 [Event(name="labelChanged",type="flash.events.Event")]
 public classButtonLabel extends Button
 {
  // property to hold labelvalue
  private var_myLabel:String;
  // public setter method
  public function setmyLabel(s:String):void
  {
   _myLabel =s;
   this.label =s;
   // Create anddispatch custom event
   vareventObj:Event = new Event("labelChanged");
   dispatchEvent(eventObj);
  }  
 }
}
Using the ButtonLabel class withthe labelChanged [Event]

 
 <fx:Script>
 <![CDATA[
  import mx.controls.Alert;
  importflash.events.Event;
  // method to handle customevent
  public functionlabelChanged(eventObj:Event):void
  {
   myTA.text=myTA.text + "\n"+ eventObj.target.label;
   myTA.verticalScrollPosition= myTA.verticalScrollPosition +20;
  }
 ]]>
 </fx:Script>
 
 <mx:Panel title="Event Sample"width="500" height="275"
  paddingTop="10"paddingLeft="10" paddingRight="10" paddingBottom=" 10"layout="absolute">
 
  <mx:TextInputid="buttonLabelTI"
   change="myButton.myLabel=buttonLabelTI.text"x="10" y="9"/>
  <!--Instantiatecustom class and define method to handle label- Changedevent-->
 
  <comps:ButtonLabelid="myButton" labelChanged="labelChanged(event);" x="10"y="39"/>
  <mx:TextAreaid="myTA" width="200" height="200" x="249"y="10"/>
 
 </mx:Panel>

上面两个例子中都用到了Event标签,告诉自定义组件,它可以监听哪些事件