Flex 3的命名空間
Flex 3定義了唯一的MXML命名空間,即MXML 2006。在Flex Builder 3中聲明MXML 2006命名空間的默認格式如下:
xmlns:mx="http://www.adobe.com/2006/mxml"
值得注意的是,很多初學者誤認爲”mx”爲命名空間。事實上,上面的語句中”mx”只是命名空間的前綴,或者說是一個“別名”。你可以將mx修改爲任意值,甚至可以使用“空前綴”,例如:
<Application xmlns="http://www.adobe.com/2006/mxml"> <Button /> </Application>
MXML 2009
如果你使用Flash Builder 4創建一個Flex 4應用程序,會發現默認情況下FB爲你創建了3個命名空間,如下所示:
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"xmlns:mx="library://ns.adobe.com/flex/halo" .... </s:Application>
情況似乎複雜了?爲了更好的理解Flex 4中的命名空間,首先需要介紹兩個名詞:“語言級命名空間”和“組件級命名空間”。
語言級命名空間
語言級命名空間聲明瞭一個MXML文件所使用的語言版本,上面實例中,
http://ns.adobe.com/mxml/2009即爲語言級命名空間,表示當前MXML文件使用的語言版本爲MXML 2009。語言級命名空間具有如下特點:
- 每個MXML文件必須聲明且只能聲明一個語言級命名空間,Flex編譯器根據這個命名空間來確定以何種方式編譯該MXML。
- 在一個應用程序中的多個MXML文件可以使用不同的命名空間(MXML 2006或MXML 2009)。
除了聲明語言版本外,語言級命名空間還定義了一組標籤,如<Script>,<Style>等等。這些標籤可以理解爲MXML的“關鍵字”。在MXML 2009中保留了MXML 2006的全部語言級標籤,並增加了一些新的標籤,以下是完整的列表:(粗體爲Flex 4新增標籤,我們將在下一章中具體介紹)
- <fx:Binding>
- <fx:Component>
- <fx:Metadata>
- <fx:Model>
- <fx:Script>
- <fx:Style>
- <fx:Declarations>
- <fx:Library>
- <fx:Definition>
- <fx:Private>
- <fx:Reparent>
- <fx:DesignLayer>
另一方面,語言級命名空間還定義了ActionScript3中的基礎數據類型的映射:
- <fx:Array>
- <fx:Boolean>
- <fx:Class>
- <fx:Date>
- <fx:Function>
- <fx:int>
- <fx:Number>
- <fx:Object>
- <fx:RegExp>
- <fx:String>
- <fx:uint>
- <fx:Vector>
- <fx:XML>
- <fx:XMLList>
組件級命名空間
顧名思義,組件級命名空間定義了組件標籤的集合,每一個組件標籤都與一個ActionScript類或MXML文件相對應。在Flex 4中共定義了兩個組件命名空間,分別是:
Spark組件空間(”library:ns.adobe.com/flex/spark“,默認別名爲“s”)
Halo組件空間(“library:ns.adobe.com/flex/halo”,默認別名爲”mx”)
之所以需要兩個命名空間主要是爲了迴避組件命名上的衝突問題。事實上,在Flex 4的早期的構建中,所有Spark組件類均以Fx作爲前綴以和Halo組件區別,例如Spark中的Application組件被命名爲FxApplication,Button組件被命名爲FxButton,以此類推。但最終Flex SDK的開發團隊放棄了這種古怪的命名方式,而改爲使用不同的命名空間。
例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8"?> <s:Applicationxmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"xmlns:mx="library://ns.adobe.com/flex/halo"> <fx:Script> <![CDATA[ protected function sparkButton_onClick(event:MouseEvent):void { haloButton.label = "Flex 4 Rocks!"; } ]]></fx:Script> <s:Button id="sparkButton" label="Spark Button"click="sparkButton_onClick(event)" /> <mx:Button id="haloButton" label="Halo Button"y="30" /> </s:Application> |
例1可以算是Flex 4的Hello,world程序,非常簡單。它分別創建了一個Spark Button組件和一個Halo Button組件,並在點擊Spark Button時將Halo Button的label設置爲“Flex 4 Rocks!”。
Flex組件到MXML標籤的映射
前面曾經提到過,每一個MXML組件標籤都對應着一個ActionScript類或者MXML文件類。那麼,Flex是如何建立起這種映射關係的呢?
其實原理並不複雜,這種映射關係主要是通過一個清單文件(Manifest.xml)來定義,一個典型的清單文件如下:
<?xml version="1.0"?> <componentPackage> <component id="Accordion"class="mx.containers.Accordion"/> <component id="AddChild" class="mx.states.AddChild"/><component id="AddChildAction" class="mx.effects.AddChildAction"/> .... </componentPackage>
Flex SDK在編譯時,會向編譯器提供清單文件和相對應的命名空間,如library://ns.adobe.com/flex/halo。編譯後的Flex框架中,就包含了那些MXML標籤與實際類定義的映射關係了,如下圖所示:
注意:多個清單文件可以使用相同的命名空間編譯,同一個類定義也可以出現在多個清單文件中,例如,對於HTTPService組件,你可以使用Halo組件空間來引用(<mx:HTTPService />),也可以使用Spark組件空間(<s:HTTPService />)來引用。
由於Flex框架本身被分爲若干個工程(Halo, Spark, RPC, AIR-framework, TextLayout等等),所以每個工程下面也都有各自定義清單文件,可以在下面目錄找到(這裏僅列出兩個):
For Halo: {SDK_ROOT}/frameworks/projects/frameworks/manifest.xml
For Spark: {SDK_ROOT}/frameworks/projects/spark/manifest.xml
值得注意的是,Flex框架組件映射的方法也可以爲一般開發者所使用,可以爲你自己的類庫創建這種URI風格的命名空間。使用URI而不是包結構類型的命名空間的一大好處是,在MXML中引用的標籤可以做與實際類所在的包結構無關,即使未來某個類由於重構,其所在的包的目錄結構變化了,引用改類的MXML也絲毫不會受到影響。
具體如何創建URI風格的命名空間.
介紹 了MXML 2009新增的標籤,包括:
- Declarations
- Vector
- Library
- Definition
- Private
- Reparent
<Declarations />
Declarations標籤是Flex 4中最常用的新增標籤。
在Flex 3中,對於一個MXML組件的直接子元素,可以有以下幾種情況:
1. 屬性標籤,例如:
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:text > <mx:String > test</mx:String > </mx:text > </mx:Label >
2. 作爲默認屬性的值,例如:
List的默認屬性爲DataProvider
<mx:List xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:ArrayCollection > .... </mx:ArrayCollection > </mx:List >
3. 作爲容器的Children:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:Button /> <mx:Label /> </mx:Canvas >
4. 聲明並創建非可視化對象:
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" > <mx:HTTPService id="sevice" /> </mx:Canvas >
在Flex 4中,對於MXML組件的直接子元素有着更加規範的定義,即:所有直接子元素或者是組件的屬性標籤,或者是作爲組件默認屬性的值而存在。 而 容器的默認屬性即爲其Children的集合(例如Group的默認屬性爲mxmlContent,DataGroup的默認屬性爲 dataProvider)。
而對於最後一種情況,在Flex 4中,在MXML中創建非可視化對象,如HTTPService, Effect, 基本數據類型等等,必需通過<Declarations/>標籤來完成。例如聲明一個HTTPService對象:
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library:ns.adobe.com/flex/spark" > <fx:Declarations > <s:HTTPService id="service" /> </fx:Declarations > </s:Group >
上面的代碼等價於ActionScript:
public MyGroup extends Group { private var service: HTTPService = new HTTPService( ) ; }
值得注意的是,Declarations標籤也可以用來聲明、創建任何可視化組件 ,但是使用該標籤創建的組件不 會被加入到DisplayList中,也不會被初始化。你可以在需要的時候再使用它。
<Vector />
Vector是Flash Player 10中新增加的數據類型(結構),大多數情況下,使用Vector比使用Array更加高效。在Flex 4中,你可以通過MXML來創建一個Vector對象,例如:
<fx:Declarations > <fx:Vector id="myVector" type="String" fixed="false" /> </fx:Declarations >
上述代碼相當於ActionScript:
public var myVector: Vector.< String> = new Vector.< String> ( 0 ,false ) ;
<Library />和<Definition />
Library標籤允許你爲當前的MXML組件聲明一個”類庫“。相應地,Definition標籤可以定義該類庫中的一個”類”。基本的語法規則 如下:
- 如果使用Library標籤,則它必須是MXML或FXG文檔中的第一個標籤。
- Library標籤可以包含一個或多個Definition標籤。
- 必須爲Definition標籤提供name屬性作爲”類名”,同時Definition標籤必須有且只能有一個直接子標籤作爲其所定義的類的基 類。
- 使用Definition標籤定義的類也可以使用<fx:Script />和<fx:MetaData />標籤。
- 由Definition標籤定義的類屬於默認包,需使用MXML 2009的命名空間來引用。如類名爲MyClass,則在MXML中使用該類的標籤爲<fx:MyClass/>。
- Library和Definition標籤不可嵌套使用,即在由Definition定義的類中,不能使用Library和Definition 標籤。
下面的代碼中,使用Library和Definition標籤創建了MyClass類及其子類MySubClass:
<!-- MyApp.mxml --> <s:Applicaiton xmlns:fx=... > <fx:Library > <!-- 此處定義了一個名爲MyClass的類,繼承自Group類 --> <fx:Definition name="MyClass" > <s:Group > <s:Rect width="200" height="200" > <s:fill .../> </s:Rect > </s:Group > </fx:Definition > <!-- 此處定義了一個名爲MySubClass的類,繼承自MyClass類> <fx:Definiton name="MySubClass" > <fx:MyClass /> </fx:Definition > </fx:Library > <!-- 使用MyClass和MySubClass類 --> <fx:MyClass /> <fx:MySubClass /> </s:Application >
此外,由Definition定義的類的實例,不能賦予id屬性(例如,在上面代碼中,如果爲MyClass實例聲明id屬性會造成編譯錯誤)。這 本質上是由Library的“私有性”決定的。在大多數情況下,該標籤會在FXG中使用,用於定義可重用的圖形元素。
小技巧
事實上,儘管不能爲Definition定義的類的實例賦予id屬性,我們仍然可以獲取這些類的 實例的引用,通過查看Flex編譯後的AS代碼(使用-keep參數)可以發現:所有由Definition定義的類最終會被轉化爲類名 爲”MXML類名_definitionN.as”這樣的獨立ActionScript類 。
例如,上面例子(MXML類名爲 MyApp)中的MyClass和MySubClass最終會被轉化爲MyApp_definition1和MyApp_definition2。在確定 這些類的實際類名後,我們可以通過一些系統事件來獲取這些類的引用並對其進行操作,例如:
<!-- Test.mxml --> <?xml version="1.0" encoding="utf-8" ?> <s:Application xmlns:fx="..." xmlns:s="..." > <fx:Library > <fx:Definition name="MyRect" > <s:Group width="100" height="100" > .... </s:Group > </fx:Definition > </fx:Library > <fx:MyRect creationComplete="myrect1_creationComplete(event)" /> <fx:Script > <![ CDATA[ import mx.events.FlexEvent; private var myRect:Test_definition1 ; <!-- 通過事件獲取實例的引用 --> protected function myrect1_creationComplete(event:FlexEvent):void { myRect = event.target as Test_definition1; myRect.x = 200; } ]]> </fx:Script > </s:Application >
<Private />
Private標籤用於提供MXML和FXG文檔的元信息,標籤內的內容會被編譯器忽略。儘管如此,你必須保證其內容是有效的XML格式。例如:
<fx:Private > <Author> Jinni Cao</Author> <Version> 1.0</Version> <Site> http://www.SWFever.com</Site> </fx:Private >