这是Flex 4 SDK 新特性教程系列的第3章。本章介绍了Flex 4引入的MXML 2009命名空间以及Flex组件与命名空间映射的机制。
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: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"> <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风格的命名空间,请参考我的另一篇教程。
在下一章中,我们将会重点介绍Flex 4中新增加的语言级标签。