Flex中的事件機(jī)制
2006-11-28 10:37
一. 事件簡(jiǎn)介
事件可以由外設(shè)觸發(fā), 比如:鍵盤,鼠標(biāo), 也可能是外部輸入, 比如:web service的返回. 事件還能由組件的外觀和生命周期發(fā)生變化時(shí)觸發(fā), 比如:組件的創(chuàng)建或者改變大小. 所有用戶與應(yīng)用交互都會(huì)產(chǎn)生事件.用戶沒有直接與應(yīng)用交互也可能產(chǎn)生事件, 比如:數(shù)據(jù)裝載完畢. 你可以在程序中使用事件監(jiān)聽器監(jiān)聽這些事件. 事件監(jiān)聽器是函數(shù)方法用于響應(yīng)指定的事件. 有時(shí)也稱之為事件處理器. Flex的事件模型基于DOM3事件模型. 組件產(chǎn)生派發(fā)事件并消費(fèi)(監(jiān)聽)其他事件.如果一個(gè)對(duì)象想要了解其他對(duì)象事件的信息, 可以注冊(cè)一個(gè)監(jiān)聽器. 當(dāng)事件發(fā)生時(shí),對(duì)象派發(fā)此事件到所有注冊(cè)過的監(jiān)聽器中. 組件有Flex提供的內(nèi)建事件. 也可以使用派發(fā)-監(jiān)聽模型定義自己的事件監(jiān)聽器, 并指定監(jiān)聽器監(jiān)聽何種事件. 二. 事件流簡(jiǎn)介 當(dāng)一個(gè)事件被派發(fā)出來時(shí), 事件對(duì)象從根節(jié)點(diǎn)開始自上而下開始掃描display list, 一直到目標(biāo)對(duì)象, 檢查每個(gè)節(jié)點(diǎn)是否有相應(yīng)的監(jiān)聽器. 目標(biāo)對(duì)象指的是display list中產(chǎn)生事件的對(duì)象. 比如: <mx:Panel> <mx:HBox> <mx:VBox> <mx:Button /> </mx:VBox> </mx:HBox> </mx:Panel> 如何此時(shí) resize了VBox, 則會(huì)從根(Application)開始, 下來檢查Panel, HBox, 直到目標(biāo)對(duì)象-產(chǎn)生resize事件的VBox為止. 三. 事件的派發(fā) Flex中可以通過dispatchEvent()方法手工派發(fā)事件, 所有UIComponent的子類都可以調(diào)用此方法. 語法: objectInstance.dispatchEvent(new Event("event_type"):Boolean 參數(shù)event_type是Event對(duì)象的type屬性. 函數(shù)的返回值總是True. 可以使用此方法派發(fā)任意事件, 而不僅僅是用戶自定義事件, 比如: 可以派發(fā)一個(gè)Button的Click事件. var result:Boolean = buttonInstance.dispatchEvent(new Event(MouseEvent.CLICK)); 在Flex應(yīng)用中不是必須對(duì)新派發(fā)的事件進(jìn)行處理, 如果觸發(fā)了一個(gè)事件, 而沒有對(duì)應(yīng)的Listener時(shí),Flex忽略此事件. 如果想給Event對(duì)象添加新屬性, 就必須繼承Event類,然后定義新屬性 四.事件的傳播: 事件觸發(fā)后, Flex有3個(gè)檢測(cè)事件監(jiān)聽器的階段, 3個(gè)階段的發(fā)生的順序如下: 1. 捕獲 2. 目標(biāo) 3. 上浮 在任意一個(gè)階段, 節(jié)點(diǎn)們都有機(jī)會(huì)操作事件. 比如: 用戶點(diǎn)擊了一個(gè)在VBox中的Button, 在捕獲階段, Flex檢查Application對(duì)象(根節(jié)點(diǎn))和VBox是否有監(jiān)聽器處理此事件. Flex然后在目標(biāo)階段觸發(fā)按鈕的監(jiān)聽器. 在上浮階段, VBox和應(yīng)用以與捕獲階段相反的順序再次獲得機(jī)會(huì)處理事件. 在Actionscript3.0中,你可以在任意目標(biāo)節(jié)點(diǎn)上注冊(cè)事件監(jiān)聽器. 但是部分事件會(huì)被直接傳給目標(biāo)節(jié)點(diǎn),比如Socket類. 捕獲階段的節(jié)點(diǎn)順序是從父節(jié)點(diǎn)到子節(jié)點(diǎn)的, 而上浮階段剛好相反. 捕獲事件缺省是關(guān)閉的,也就是說如果要捕獲事件, 必須顯式指定在捕獲階段進(jìn)行處理. 每一個(gè)Event都有target和currentTarget屬性, 幫助跟蹤事件傳播的過程. 捕獲階段: 在捕獲階段,Flex在顯示列表中檢查事件的祖先是否注冊(cè)了事件的監(jiān)聽器. Flex從根節(jié)點(diǎn)開始順序而下. 大多數(shù)情況中, 根節(jié)點(diǎn)是Application對(duì)象. 同時(shí), Flex改變事件的currentTarget值. 缺省情況下, 在此階段,沒有容器監(jiān)聽事件. use_capture參數(shù)的值是False,在此階段添加監(jiān)聽的唯一方法是在調(diào)用add_listener時(shí), 傳入一個(gè)為True值的use_capture參數(shù), 比如: myAccordion.addEventListener(MouseEvent.MOUSE_DOWN, customLogEvent, true); 如果是在Mxml中添加監(jiān)聽, Flex設(shè)置此參數(shù)為False, 沒有辦法進(jìn)行修改. 如果設(shè)置了use_capture為True, 那么事件將不會(huì)上浮. 如果既想捕獲又想上浮就必須調(diào)用 addEventListener兩次. 一次use_capture參數(shù)為true, 一次為false; 捕獲很少使用, 上浮的使用更為普遍. 目標(biāo)階段: 在目標(biāo)階段, Flex激發(fā)事件的監(jiān)聽程序, 不檢查其他的節(jié)點(diǎn). 上浮階段: 事件只在bubbles屬性為True時(shí)才進(jìn)行上浮. 可以上浮的事件包括: change, click, doubleClick, keyDown, keyUp, mouseDown, mouseUp. 在上浮階段, Flex改變事件的currentTarget屬性, 而target屬性是初始派發(fā)事件的對(duì)象. 查詢事件階段: 使用事件的eventPhase可以獲得事件當(dāng)前的階段, 1: CAPTURE_PHASE 2: AT_TARGET 3: BUBBLING_PHASE 示例: private function determineState(event:MouseEvent):Void { Debug.trace(event.eventPhase + ":" + event.currentTarget.id); } 停止傳播: 使用下面兩個(gè)函數(shù)停止事件的傳播: stopPropagation() stopImmediatePropagation() |
? ?? ? 在Flex中定義事件有兩中情況,分別是ActionScript和MXML中定義。
? ?? ? 在ActionScript中定義:
CODE:
[Event(name="myEnableEvent", type="flash.events.Event")]
public class MyComponent extends UIComponent
{
? ?? ?? ???...
}
在MXML中定義:public class MyComponent extends UIComponent
{
? ?? ?? ???...
}
CODE:
<mx:Metadata>
? ? [Event(name="DataChange", type="DataChangeEvent")]
</mx:Metadata>
DataChangeEvent事件參數(shù)的定義:? ? [Event(name="DataChange", type="DataChangeEvent")]
</mx:Metadata>
CODE:
import flash.events.Event;
public class DataChangeEvent extends flash.events.Event
{
? ?? ? public function DataChangeEvent()
? ?? ? {
? ?? ?? ?? ???super("DataChange");
? ?? ? }
? ?? ? public var Data:Object;
}
在自定義控件中定義和觸發(fā)事件:public class DataChangeEvent extends flash.events.Event
{
? ?? ? public function DataChangeEvent()
? ?? ? {
? ?? ?? ?? ???super("DataChange");
? ?? ? }
? ?? ? public var Data:Object;
}
CODE:
<?xml version="1.0" encoding="utf-8"?>
<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="212" height="56">
<mx:Metadata>
? ?? ???[Event(name="DataChange", type="DataChangeEvent")]
? ? </mx:Metadata>
<mx:Button label="Button" click="Change()"/>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?function Change():void
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ? this.dispatchEvent(new DataChangeEvent());
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Form>
容器接收相關(guān)自定義控件事件:<mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="212" height="56">
<mx:Metadata>
? ?? ???[Event(name="DataChange", type="DataChangeEvent")]
? ? </mx:Metadata>
<mx:Button label="Button" click="Change()"/>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?function Change():void
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ? this.dispatchEvent(new DataChangeEvent());
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Form>
CODE:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="*">
? ?? ?
? ?? ? <ns1:EmployeeCombo x="146" y="132" DataChange="onChange(event)" >
? ?? ? </ns1:EmployeeCombo>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?import mx.controls.Alert;
? ?? ?? ?? ?? ?? ?? ?function onChange(e:DataChangeEvent)
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Application>
其實(shí)自定義事件的現(xiàn)實(shí)也很簡(jiǎn)單,但起著非常重要的作用;正是因?yàn)橛辛耸录臋C(jī)制,使得大部分重復(fù)的功能抽取到自定義控件中,從而達(dá)到一個(gè)很高的代碼重用性。
? ?? ?
? ?? ? <ns1:EmployeeCombo x="146" y="132" DataChange="onChange(event)" >
? ?? ? </ns1:EmployeeCombo>
? ?? ? <mx:Script>
? ?? ?? ?? ???<![CDATA[
? ?? ?? ?? ?? ?? ?? ?import mx.controls.Alert;
? ?? ?? ?? ?? ?? ?? ?function onChange(e:DataChangeEvent)
? ?? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???]]>
? ?? ? </mx:Script>
</mx:Application>