需要说明的是,这里的“纯Flash应用”是指不依赖于Flex框架的Flash应用程序。这似乎是个匪夷所思的命题,MXML不是Flex所特有的语言吗?
Ryan Campbell的这篇文章给出了一个实例。MinimalComps是一个开源的AS类库,实现了一些轻量级的UI控件。 Ryan的实例演示了如何使用MXML和MinimalComps来创造一个完全不依赖于Flex框架的Flash应用。该实例编译后的结果只有23K。更酷的是,MXML中的一些高级特性,如Data Binding也完全可以正常工作!
如果你肯花一点时间稍作分析的话,会发现实现它其实并不需要什么高深的技巧,主要在于你对编译器工作方式的了解:
1) Flex编译器(mxmlc)并不要求MXML主文件必须继承自mx.core.Application类,任何一个继承自flash.display.Sprite的类都可以作为应用程序入口。
因此理论上最简单的MXML应用程序如下所示:
<?xml version="1.0" encoding="utf-8"?> <f:Sprite xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:f="flash.display.*" />
这个应用程序经过Flex 4编译器编译后的文件大小只有不到200字节!而一个Flex应用程序则至少在200KB以上。
2)Flex编译器对[DefaultProperty]的支持
在Flex 4中,一个MXML组件的直接子标签被解释为对该组件的默认属性赋值,默认属性通过[DefaultProperty]来声明。
(Flex 3编译器也支持组件的[DefaultProperty]声明,但经过我的测试,Flex 3编译器会忽略应用程序根节点的[DefaultProperty]声明)
例如:
<?xml version="1.0" encoding="utf-8"?> <swfever:MyContainer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:swfever="com.swfever.*" xmlns:flash="flash.display.*"> <flash:Sprite id="sprite1" /> <flash:Sprite id="sprite2" /> </swfever:MyContainer>
MyContainer的定义如下:
package com.swfever { import flash.display.DisplayObject; import flash.display.Sprite; [DefaultProperty("content")] public class MyContainer extends Sprite { private var _content:Array; public function MyContainer() { } public function set content(value:Array):void { _content = value; updateContent(); } public function get content():Array { return _content; } private function updateContent():void { while(numChildren) { removeChildAt(0); } for each(var item:DisplayObject in content) { trace("Add item:"+item); addChild(item); } } } }
上面的代码只是为了简单说明其工作原理,如果你打算编写自己的UI框架,应该参考Flex的“推迟”机制,将UI更新(addChild/removeChild)推迟到渲染前进行,而不是每次content被赋值时都进行更新。