- 浏览: 67203 次
- 性别:
- 来自: 北京
最新评论
-
_MyCould:
Flex Module基础 -
szlaptop:
这个正式我一直想的,楼主,能帖图上来看看吗?谢谢
最近完成的某系统的报表组件 -
wfzhanga:
楼主整理的不错,能不能把代码传上去啊。如果方便请帮我传一下啊, ...
flex ToolTip专题 -
bence:
总结的很好,谢谢分享
Flex Metadata Tag高级应用 -
fansfirst2008:
楼主太强了,不仅把东西讲解得深入浅出,而且写的文字表达很漂亮! ...
flex itemRenderer使用(一)内联渲染器
Module加载方式概览
在理解这种加载方式之前,我们应该首先知道什么是Module模块。Module 实际上是一个预编译的SWF文件。虽然是SWF格式的文件,但是这个文件不能独立运行,并且只能被ModuleLoader加载后才能显示。逻辑上它是一个容器,可以像一般的容器一样包含别的容器,组件,甚至是别的Module模块。根据需要,预编译的Module模块可以被应用加载和卸载。不同的应用可以共享这些Module模块。Flex应用可以被分割为若干个预编译的Module模块,可以在需要时分别加载这些模块,避免在系统初始化时加载全部子容器。采用这种方式的Flex应用从设计上分隔了逻辑相对独立的模块,减少了系统初始化时的加载时间。
Module的创建、编译、加载和卸载方法
我们有两种方式创建一个Module模块,一是利用MXML标签<mx:Module>创建Module类;令一种方式采用ModuleManager类在ActionScript中创建Module模块类。模块类创建后将被编译成SWF文件。如前面章节所述我们可以利用mxmlc编译器手动编译或者在Flex Builder3集成开发环境提供的工具自动编译Module类为SWF文件。这里介绍采用Flex Builder3集成开发环境提供的方式创建一个Module类。
在FlexBuilder3中创建基于MXML标签的Module模块
创建基于MXML标签的Module模块,需要扩展mx.modules.Module.
1. 第一步,在Flex Builder3集成开发环境中创建一个Flex项目Moduler。
2. 第二步,选择FileàNewàMXML Module
3. 第三步,输入Module文件名字为MXMLDemoModule,设置Module的高度和宽度,选择Module容器的布局方式为absolute.,选择默认的预编译后优化的SWF选项,单击Finish按钮。
4. Module文件被创建,编辑Module文件,在此例中我们可以假定是一个登陆Module界面,
其源代码为,
集成登陆Module模块到主应用文件ModulerApp.mxml,
创建基于ActionScript的Module模块
在ActionScript中创建的Module模块类大都继承了mx.modules.Module或者mx.modules.ModuleBase基础类。我们都知道,MXML标签<mx:Module>实际上是mx.modules.Module类的另一种表现方式,这也就不难理解无论在MXML标签中还是在ActionScript中创建Module模块其实都是相通的。自定义Module类继承mx.modules.Module和继承mx.modules.ModuleBase两个基类的不同是,继承自前者的或者基于<mx:Module>标签的自定义Module组件将被加入到框架可视化显示列表,后者则没有。参考示例
编译Module模块
前面已经提及我们有两种方式来编译Module模块文件。像编译主应用文件一样,一种是在命令行手动编译,最简单的情形 可以利用这个命令
Mxmlc MyModule.mxml
另一种是在Flex Builder3中提供的自动编译工具编译。编译的结果是一个可以被装载的SWF文件,与编译后的SWF主应用文件最大的不同就是,模块SWF文件不能独立运行,只能在被装载后才能够和其宿主共同运行。
怎样装载和卸载Module模块
总体来说,有几种方式可以实现Module模块的装载和卸载。
利用ModuleLoader:ModuleLoader类提供了一系列高层处理Module的编程接口。
利用ModuleManager: ModuleManager类提供了低层次的处理Module的装载卸载以及事件响应等的变成接口。
下面将详细地讲解这两种处理方式。
我们可以利用ModuleLoader类在主应用文件或者别的Module模块中加载任意预编译的Module对象。最简单的方式是采用ModuleLoader类的标签形式<mx:ModuleLoader>在主应用的MXML文件中显式地加载Module,然后只需要设置这个标签的url属性为预编译Module的SWF文件位置,可以是相对路径,也可以是绝对路径。参考实例,
编程时我们可以根据需要替换此url所指向的模块位置,实现不同模块的更迭显示。当ModuleLoader类初始化时或者每次更改这个url属性值时,这个ModuleLoader类的loadModule()方法被触发。如果设定url属性为空字符串,ModuleLoader卸载当前加载的Module模块。
ModuleLoader其实是一种特殊的导航式容器。和一般导航式容器如ViewStack不同的是,ModuleLoader不必在初始化时携带加载所有的孩子组件。了解这一点,我们可以猜想到,在一个Flex主应用中可以包含甚至嵌套包含多个ModuleLoader实例,以下示例展示在一个ViewStack容器中包含多个ModuleLoader的示例。
同时我们可以利用ModuleLoader类提供的loadModule()和unloadModule()方法动态地指定被加载的Module模块。这两个方法没有输入形参,调用时分别加载和卸载当前ModuleLoader实例url属性所指向的Module模块。下面示例展示了在TabNavigator容器中,按钮点击后分别加载卸载不同的Module模块
我们当然也可以利用ModuleManager类来加载Module模块。这种方式比起纯粹的ModuleLoader方式稍微复杂一点,但是ModuleManager提供了比ModuleLoader更加强大的能力来管理Module模块的加载过程。具体操作可以分成以下几步
通过ModuleManager实例的getModule()方法拿到Module模块的一个索引,索引类型为IModuleInfo。
调用这个索引的load()方法。
利用这个接口的factory属性拿到它相关连的Module工厂,调用此工厂的create()方法,并将返回值强制转换成当前的Module类型。
参考示例
理论上说,Flex应用第一次启动时初始化下载的大小,集成了Module模块的应用相对比没有集成Module模块的相似应用要小一些。这减少了初始化页面的等待时间。甚至在Module模块的SWF文件还没有下载完毕的时候,主应用文件也可以顺利显示。Module模块第一次加载时将被缓存在客户端IE, 已缓存的Module模块被再次加载时,FlashPlayer将直接在缓存中加载Module实例,减少了加载时间,提高了用户体验。当然这有一个前提就是,客户端IE没有被清空。所以在实际操作中,你可以在SWF模块真正的被使用之前将其预加载到客户端缓存。方法是调用ModuleManager.getModule("Module1.swf").load()语句。在调用create()方法之前并没有创建这个模块实例,而只是纯粹地将模块SWF文件加载到客户端内存。下面实例展示了在系统初始化时预先加载一个名字叫做Module1.swf的模块,当此模块需要显示时才创建这个Module模块实例。
怎样处理ModuleLoader事件
我们不仅可以以上述的方式加载卸载预编译Module模块,而且更进一步,也可以捕捉和处理模块在加载卸载过程中可能会触发的各种事件。这些事件由ModuleLoader触发,分别有setup,ready,loading,unload,progress,error和urlChanged等。很好的利用这些内置的事件可以使我们更加精细地跟踪模块加载卸载过程,实现更加强大的功能。下述示例展示了一个自定义的ModuleLoader组件CustomModuleLoader,这个组件会跟踪当模块实例被主应用加载时所有触发的事件。
应用error事件
使用ModuleLoader的error事件可以允许开发者在当不知什么原因Module模块没有被加载或卸载成功的时候,做一些必要的动作。参考以下示例
应用progress事件
使用ModuleLoader的progress事件可以让你跟踪模块实例加载的进度信息。参考示例,
怎样共享和传输Module模块间数据
Module模块是一个容器,每个独立的模块对象都相当于一个自定义组件。有以下几种方式可以实现模块-模块、模块-主应用、主应用-模块、模块-一般自定义组件间的数据传输和通信。
利用ModuleLoader的child、ModuleManager的factory、以及Application的parentApplication属性存取Module模块和主应用文件对象索引。
因为Module模块在ModuleLoader中通常用url属性来指定,所以我们可以通过在url上面拼GET参数,然后在Module模块中解析这些拼上去的参数的方式来传输数据。
通过ActionScript接口方式。你可以定义一个ActionScript接口,这个接口定义了一系列方法和属性。Module模块和主应用Application都可以访问这些属性。从而实现数据共享。
在主应用Application中访问Module模块对象
我们可以在主应用Application中访问子Module模块对象中定义的方法和属性。下面示例展示了通过ModuleLoader的child属性拿到子Module模块对象索引,然后调用其定义的公共方法getTitle().
Module模块文件,
通过这种方式得到子Module模块的索引导致了主应用Application和Module模块之间的紧耦合,不利于模块逻辑的重用。同样地,利用ModuleManager的factory属性也可以拿到当前ModuleLoader的子模块对象的索引。参考以下示例,模块文件为,
主应用Application为,
在Module模块对象中存取主应用Application
Module模块可以通过其parentApplication属性拿到主应用Application对象的索引,通过这个索引可以访问主应用对象的公共方法和属性。参考以下示例,Module模块文件为,
主应用文件为,
<?xml version="1.0"?>
不过这种方式导致的一个缺点是,自定义的Module模块文件的可移植特性将大打折扣。
在一个Module模块对象中存取另一个Module模块对象
同样地,我们也可以利用ModuleLoader的child属性,在一个Module模块对象中拿到另一个Module模块对象的索引,通过这个索引访问当前Module模块对象的公共方法和属性。参考以下示例,主应用文件,
Module1文件,
Module2文件,
通过拼ModuleLoader的url参数方式实现数据传输
在url上面拼GET参数基本上是这种格式,url=module1.swf?param1=value1¶m2=value2
比如在主应用文件Application中拼一系列GET参数到ModuleLoader的url属性上,在Module模块文件中解析并处理这些参数,参考以下示例,主应用文件,
模块文件,
利用ActionScript接口实现Module模块间的数据通信
在面向对象的编程中,我们讲要面向接口编程。面向接口的编程方式从一定程度上解决了相互关联的模块间的紧密耦合问题。以上提到的所有数据传输和共享方式都在不同程度上导致了模块间的紧耦合。不过,Flex提供了一种利用标准的ActionScript接口实现Module模块间数据通信的方式。具体地说,对于Module模块对象和主应用Application对象间的通信,我们可以定义一个ActionScript接口,Module模块对象实现了这个接口中定义的方法和属性,那么主应用Application就可以访问这个接口中定义的属性和方法。接口中定义了Module模块对象和主应用Application需要共享的数据和方法,是两者间共同的一个契约,同时也实现了接口和实现的分离,达到了松耦合的目的。参考以下示例,主应用Application,
接口文件,
// modules/interfaceexample/IModuleInterface
Module模块文件,
在理解这种加载方式之前,我们应该首先知道什么是Module模块。Module 实际上是一个预编译的SWF文件。虽然是SWF格式的文件,但是这个文件不能独立运行,并且只能被ModuleLoader加载后才能显示。逻辑上它是一个容器,可以像一般的容器一样包含别的容器,组件,甚至是别的Module模块。根据需要,预编译的Module模块可以被应用加载和卸载。不同的应用可以共享这些Module模块。Flex应用可以被分割为若干个预编译的Module模块,可以在需要时分别加载这些模块,避免在系统初始化时加载全部子容器。采用这种方式的Flex应用从设计上分隔了逻辑相对独立的模块,减少了系统初始化时的加载时间。
Module的创建、编译、加载和卸载方法
我们有两种方式创建一个Module模块,一是利用MXML标签<mx:Module>创建Module类;令一种方式采用ModuleManager类在ActionScript中创建Module模块类。模块类创建后将被编译成SWF文件。如前面章节所述我们可以利用mxmlc编译器手动编译或者在Flex Builder3集成开发环境提供的工具自动编译Module类为SWF文件。这里介绍采用Flex Builder3集成开发环境提供的方式创建一个Module类。
在FlexBuilder3中创建基于MXML标签的Module模块
创建基于MXML标签的Module模块,需要扩展mx.modules.Module.
1. 第一步,在Flex Builder3集成开发环境中创建一个Flex项目Moduler。
2. 第二步,选择FileàNewàMXML Module
3. 第三步,输入Module文件名字为MXMLDemoModule,设置Module的高度和宽度,选择Module容器的布局方式为absolute.,选择默认的预编译后优化的SWF选项,单击Finish按钮。
4. Module文件被创建,编辑Module文件,在此例中我们可以假定是一个登陆Module界面,
其源代码为,
<?xml version="1.0" encoding="utf-8"?> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="400" height="300"> <mx:Panel width="300" height="220" layout="absolute" horizontalCenter="0" verticalCenter="0" backgroundAlpha="0.5"> <mx:Form horizontalCenter="0" verticalCenter="0" paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0"> <mx:FormItem label="Account" indicatorGap="5"> <mx:TextInput borderStyle="solid" id="account" text="admin"/> </mx:FormItem> <mx:FormItem label="Password" indicatorGap="5"> <mx:TextInput borderStyle="solid" id="password" text="admin" displayAsPassword="true"/> </mx:FormItem> <mx:FormItem direction="horizontal" > <mx:Button id="logined" label="Login" styleName="blueButton"/> <mx:Button id="reset" label="Reset" styleName="greenButton"/> </mx:FormItem> </mx:Form> </mx:Panel> <mx:Label text="CopyRight 2008 demo Solutions" horizontalCenter="0" verticalCenter="252.5"/> </mx:Module>
集成登陆Module模块到主应用文件ModulerApp.mxml,
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ModuleLoader url="MXMLDemoModule.swf"/> </mx:Application>
创建基于ActionScript的Module模块
在ActionScript中创建的Module模块类大都继承了mx.modules.Module或者mx.modules.ModuleBase基础类。我们都知道,MXML标签<mx:Module>实际上是mx.modules.Module类的另一种表现方式,这也就不难理解无论在MXML标签中还是在ActionScript中创建Module模块其实都是相通的。自定义Module类继承mx.modules.Module和继承mx.modules.ModuleBase两个基类的不同是,继承自前者的或者基于<mx:Module>标签的自定义Module组件将被加入到框架可视化显示列表,后者则没有。参考示例
package { import mx.modules.ModuleBase; public class MyModule extends ModuleBase { public function MyModule() { trace("MyModule was created!"); } } }
编译Module模块
前面已经提及我们有两种方式来编译Module模块文件。像编译主应用文件一样,一种是在命令行手动编译,最简单的情形 可以利用这个命令
Mxmlc MyModule.mxml
另一种是在Flex Builder3中提供的自动编译工具编译。编译的结果是一个可以被装载的SWF文件,与编译后的SWF主应用文件最大的不同就是,模块SWF文件不能独立运行,只能在被装载后才能够和其宿主共同运行。
怎样装载和卸载Module模块
总体来说,有几种方式可以实现Module模块的装载和卸载。
利用ModuleLoader:ModuleLoader类提供了一系列高层处理Module的编程接口。
利用ModuleManager: ModuleManager类提供了低层次的处理Module的装载卸载以及事件响应等的变成接口。
下面将详细地讲解这两种处理方式。
我们可以利用ModuleLoader类在主应用文件或者别的Module模块中加载任意预编译的Module对象。最简单的方式是采用ModuleLoader类的标签形式<mx:ModuleLoader>在主应用的MXML文件中显式地加载Module,然后只需要设置这个标签的url属性为预编译Module的SWF文件位置,可以是相对路径,也可以是绝对路径。参考实例,
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:ModuleLoader url="MXMLDemoModule.swf"/> </mx:Application>
编程时我们可以根据需要替换此url所指向的模块位置,实现不同模块的更迭显示。当ModuleLoader类初始化时或者每次更改这个url属性值时,这个ModuleLoader类的loadModule()方法被触发。如果设定url属性为空字符串,ModuleLoader卸载当前加载的Module模块。
ModuleLoader其实是一种特殊的导航式容器。和一般导航式容器如ViewStack不同的是,ModuleLoader不必在初始化时携带加载所有的孩子组件。了解这一点,我们可以猜想到,在一个Flex主应用中可以包含甚至嵌套包含多个ModuleLoader实例,以下示例展示在一个ViewStack容器中包含多个ModuleLoader的示例。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Panel title="Multiple Modules Demo " height="100%" width="100%" paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0" > <mx:VBox id="v1" label="Module1"> <mx:Label id="l1" text="Module1.swf"/> <mx:ModuleLoader url="Module1.swf"/> </mx:VBox> <mx:VBox id="v2" label="Module2"> <mx:Label id="l2" text="Module2.swf"/> <mx:ModuleLoader url="Module2.swf"/> </mx:VBox> <mx:VBox id="v3" label="Module3"> <mx:Label id="l3" text="Module3.swf"/> <mx:ModuleLoader url="Module3.swf"/> </mx:VBox> </mx:TabNavigator> </mx:Panel> </mx:Application>
同时我们可以利用ModuleLoader类提供的loadModule()和unloadModule()方法动态地指定被加载的Module模块。这两个方法没有输入形参,调用时分别加载和卸载当前ModuleLoader实例url属性所指向的Module模块。下面示例展示了在TabNavigator容器中,按钮点击后分别加载卸载不同的Module模块
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.modules.*; public function moduleLoader(m:ModuleLoader, s:String):void { if (!m.url) { m.url = s; return; } m.loadModule(); } public function moduleUnloader(m:ModuleLoader):void { m.unloadModule(); } ]]> </mx:Script> <mx:Panel title="Dynamically load/unload multiple Modules" height="100%" width="100%" paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0" > <mx:TabNavigator id="navigator" width="100%" height="100%" creationPolicy="all" > <mx:VBox id="vb1" label="Module1"> <mx:Button label="Load" click="moduleLoader(moduleLoader, l1.text)" /> <mx:Button label="Unload" click="moduleUnloader(moduleLoader)" /> <mx:Label id="l1" text="Module1.swf"/> <mx:ModuleLoader id="moduleLoader"/> </mx:VBox> <mx:VBox id="vb2" label="Module2"> <mx:Button label="Load" click="moduleLoader(moduleLoader2, l2.text)"/> <mx:Button label="Unload" click="removeModule(moduleLoader2)" /> <mx:Label id="l2" text="Module2.swf"/> <mx:ModuleLoader id="moduleLoader2"/> </mx:VBox> <mx:VBox id="vb3" label="Module3"> <mx:Button label="Load" click="moduleLoader(moduleLoader3, l3.text)"/> <mx:Button label="Unload" click="removeModule(moduleLoader3)" /> <mx:Label id="l3" text="Module3.swf"/> <mx:ModuleLoader id="moduleLoader3"/> </mx:VBox> </mx:TabNavigator> </mx:Panel> </mx:Application>
我们当然也可以利用ModuleManager类来加载Module模块。这种方式比起纯粹的ModuleLoader方式稍微复杂一点,但是ModuleManager提供了比ModuleLoader更加强大的能力来管理Module模块的加载过程。具体操作可以分成以下几步
通过ModuleManager实例的getModule()方法拿到Module模块的一个索引,索引类型为IModuleInfo。
调用这个索引的load()方法。
利用这个接口的factory属性拿到它相关连的Module工厂,调用此工厂的create()方法,并将返回值强制转换成当前的Module类型。
参考示例
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import mx.modules.ModuleManager; import mx.modules.IModuleInfo; public var info:IModuleInfo; private function init():void { info = ModuleManager.getModule("Module1.swf"); info.addEventListener(ModuleEvent.READY, moduleEventHandler); info.load(); } private function moduleEventHandler(e:ModuleEvent):void { vb.addChild(info.factory.create() as Module1); } ]]> </mx:Script> <mx:VBox id="vb"/> </mx:Application>
理论上说,Flex应用第一次启动时初始化下载的大小,集成了Module模块的应用相对比没有集成Module模块的相似应用要小一些。这减少了初始化页面的等待时间。甚至在Module模块的SWF文件还没有下载完毕的时候,主应用文件也可以顺利显示。Module模块第一次加载时将被缓存在客户端IE, 已缓存的Module模块被再次加载时,FlashPlayer将直接在缓存中加载Module实例,减少了加载时间,提高了用户体验。当然这有一个前提就是,客户端IE没有被清空。所以在实际操作中,你可以在SWF模块真正的被使用之前将其预加载到客户端缓存。方法是调用ModuleManager.getModule("Module1.swf").load()语句。在调用create()方法之前并没有创建这个模块实例,而只是纯粹地将模块SWF文件加载到客户端内存。下面实例展示了在系统初始化时预先加载一个名字叫做Module1.swf的模块,当此模块需要显示时才创建这个Module模块实例。
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="modulePreloader()"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import mx.modules.ModuleManager; import mx.modules.IModuleInfo; private function modulePreloader():void { var info:IModuleInfo = ModuleManager.getModule("Module1.swf"); info.addEventListener(ModuleEvent.READY, moduleEventHandler); info.load(); } private function moduleEventHandler(e:ModuleEvent):void { trace('' + e.type); } ]]> </mx:Script> <mx:Panel title="Module Preloader" height="100%" width="100%" > <mx:TabNavigator id="tn" width="100%" height="100%" creationPolicy="all" > <mx:VBox id="vb1" label="Module1"> <mx:ModuleLoader url="Module1.swf"/> </mx:VBox> </mx:TabNavigator> </mx:Panel> </mx:Application>
怎样处理ModuleLoader事件
我们不仅可以以上述的方式加载卸载预编译Module模块,而且更进一步,也可以捕捉和处理模块在加载卸载过程中可能会触发的各种事件。这些事件由ModuleLoader触发,分别有setup,ready,loading,unload,progress,error和urlChanged等。很好的利用这些内置的事件可以使我们更加精细地跟踪模块加载卸载过程,实现更加强大的功能。下述示例展示了一个自定义的ModuleLoader组件CustomModuleLoader,这个组件会跟踪当模块实例被主应用加载时所有触发的事件。
<?xml version="1.0" encoding="iso-8859-1"?> <mx:ModuleLoader xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" creationComplete="init()"> <mx:Script> <![CDATA[ public function init():void { addEventListener("urlChanged", onUrlChanged); addEventListener("loading", onLoading); addEventListener("progress", onProgress); addEventListener("setup", onSetup); addEventListener("ready", onReady); addEventListener("error", onError); addEventListener("unload", onUnload); standin = panel; removeChild(standin); } public function onUrlChanged(event:Event):void { if (url == null) { if (contains(standin)) removeChild(standin); } else { if (!contains(standin)) addChild(standin); } progress.indeterminate=true; unload.enabled=false; reload.enabled=false; } public function onLoading(event:Event):void { progress.label="Loading module " + url; if (!contains(standin)) addChild(standin); progress.indeterminate=true; unload.enabled=false; reload.enabled=false; } public function onProgress(event:Event):void { progress.label="Loaded %1 of %2 bytes..."; progress.indeterminate=false; unload.enabled=true; reload.enabled=false; } public function onSetup(event:Event):void { progress.label="Module " + url + " initialized!"; progress.indeterminate=false; unload.enabled=true; reload.enabled=true; } public function onReady(event:Event):void { progress.label="Module " + url + " successfully loaded!"; unload.enabled=true; reload.enabled=true; if (contains(standin)) removeChild(standin); } public function onError(event:Event):void { progress.label="Error loading module " + url; unload.enabled=false; reload.enabled=true; } public function onUnload(event:Event):void { if (url == null) { if (contains(standin)) removeChild(standin); } else { if (!contains(standin)) addChild(standin); } progress.indeterminate=true; progress.label="Module " + url + " was unloaded!"; unload.enabled=false; reload.enabled=true; } public var standin:DisplayObject; ]]> </mx:Script> <mx:Panel id="panel" width="100%"> <mx:ProgressBar width="100%" id="progress" source="{this}"/> <mx:HBox width="100%"> <mx:Button id="unload" label="Unload Module" click="unloadModule()" /> <mx:Button id="reload" label="Reload Module" click="unloadModule();loadModule()" /> </mx:HBox> </mx:Panel> </mx:ModuleLoader> <?xml version="1.0"?> <mx:Application xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ [Bindable] public var selectedItem:Object; ]]> </mx:Script> <mx:ComboBox width="215" labelField="label" close="selectedItem=ComboBox(event.target).selectedItem" > <mx:dataProvider> <mx:Object label="Select Coverage"/> <mx:Object label="Life Insurance" module="insurancemodules/LifeInsurance.swf" /> <mx:Object label="Auto Insurance" module="insurancemodules/AutoInsurance.swf" /> <mx:Object label="Home Insurance" module="insurancemodules/HomeInsurance.swf" /> </mx:dataProvider> </mx:ComboBox> <mx:Panel width="100%" height="100%"> <CustomModuleLoader id="mod" width="100%" url="{selectedItem.module}" /> </mx:Panel> <mx:HBox> <mx:Button label="Unload" click="mod.unloadModule()"/> <mx:Button label="Nullify" click="mod.url = null"/> </mx:HBox> </mx:Application>
应用error事件
使用ModuleLoader的error事件可以允许开发者在当不知什么原因Module模块没有被加载或卸载成功的时候,做一些必要的动作。参考以下示例
<?xml version="1.0"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import mx.modules.*; import mx.controls.Alert; private function errorHandler(e:ModuleEvent):void { Alert.show("There was an error loading the module." + " Please contact the Help Desk."); trace(e.errorText); } public function createModule():void { if (chartModuleLoader.url == ti1.text) { // If they are the same, call loadModule. chartModuleLoader.loadModule(); } else { // If they are not the same, then change the url, // which triggers a call to the loadModule() method. chartModuleLoader.url = ti1.text; } } public function removeModule():void { chartModuleLoader.unloadModule(); } ]]> </mx:Script> <mx:Panel title="Module Example" height="90%" width="90%" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" > <mx:HBox> <mx:Label text="URL:"/> <mx:TextInput width="200" id="ti1" text="ColumnChartModule.swf"/ > <mx:Button label="Load" click="createModule()"/> <mx:Button label="Unload" click="removeModule()"/> </mx:HBox> <mx:ModuleLoader id="chartModuleLoader" error="errorHandler(event)"/ > </mx:Panel> </mx:Application>
应用progress事件
使用ModuleLoader的progress事件可以让你跟踪模块实例加载的进度信息。参考示例,
<?xml version="1.0"?> <!-- modules/SimpleProgressEventHandler.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import flash.events.ProgressEvent; import mx.modules.*; [Bindable] public var progBar:String = ""; [Bindable] public var progMessage:String = ""; private function progressEventHandler(e:ProgressEvent):void { progBar += "."; progMessage = "Module " + Math.round((e.bytesLoaded/e.bytesTotal) * 100) + "% loaded"; } public function createModule():void { chartModuleLoader.loadModule(); } public function removeModule():void { chartModuleLoader.unloadModule(); progBar = ""; progMessage = ""; } ]]> </mx:Script> <mx:Panel title="Module Example" height="90%" width="90%" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10" > <mx:HBox> <mx:Label id="l2" text="{progMessage}"/> <mx:Label id="l1" text="{progBar}"/> </mx:HBox> <mx:Button label="Load" click="createModule()"/> <mx:Button label="Unload" click="removeModule()"/> <mx:ModuleLoader id="chartModuleLoader" url="ColumnChartModule.swf" progress="progressEventHandler(event)" /> </mx:Panel> </mx:Application>
怎样共享和传输Module模块间数据
Module模块是一个容器,每个独立的模块对象都相当于一个自定义组件。有以下几种方式可以实现模块-模块、模块-主应用、主应用-模块、模块-一般自定义组件间的数据传输和通信。
利用ModuleLoader的child、ModuleManager的factory、以及Application的parentApplication属性存取Module模块和主应用文件对象索引。
因为Module模块在ModuleLoader中通常用url属性来指定,所以我们可以通过在url上面拼GET参数,然后在Module模块中解析这些拼上去的参数的方式来传输数据。
通过ActionScript接口方式。你可以定义一个ActionScript接口,这个接口定义了一系列方法和属性。Module模块和主应用Application都可以访问这些属性。从而实现数据共享。
在主应用Application中访问Module模块对象
我们可以在主应用Application中访问子Module模块对象中定义的方法和属性。下面示例展示了通过ModuleLoader的child属性拿到子Module模块对象索引,然后调用其定义的公共方法getTitle().
<?xml version="1.0"?> <!-- modules/ParentApplication.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script><![CDATA[ [Bindable] private var s:String; private function getTitle():void { s = (m1.child as ChildModule1).getModTitle(); } ]]></mx:Script> <mx:Label id="l1" text="{s}"/> <mx:ModuleLoader url="ChildModule1.swf" id="m1" ready="getTitle()"/> </mx:Application>
Module模块文件,
<?xml version="1.0"?> <!-- modules/ChildModule1.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"> <mx:Script><![CDATA[ // Defines the method that the application calls. public function getModTitle():String { return "Child Module 1"; } ]]></mx:Script> </mx:Module>
通过这种方式得到子Module模块的索引导致了主应用Application和Module模块之间的紧耦合,不利于模块逻辑的重用。同样地,利用ModuleManager的factory属性也可以拿到当前ModuleLoader的子模块对象的索引。参考以下示例,模块文件为,
<?xml version="1.0"?> <!-- modules/mxmlmodules/SimpleModule.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ public function computeAnswer(a:Number, b:Number):Number { return a + b; } ]]> </mx:Script> </mx:Module>
主应用Application为,
<?xml version="1.0"?> <!-- modules/mxmlmodules/SimpleMXMLApp.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp()"> <mx:Script> <![CDATA[ import mx.modules.IModuleInfo; import mx.modules.ModuleManager; public var assetModule:IModuleInfo; public var sm:Object; [Bindable] public var answer:Number = 0; public function initApp():void { // Get the IModuleInfo interface for the specified URL. assetModule = ModuleManager.getModule("SimpleModule.swf"); assetModule.addEventListener("ready", getModuleInstance); assetModule.load(); } public function getModuleInstance(e:Event):void { // Get an instance of the module. sm = assetModule.factory.create() as SimpleModule; } public function addNumbers():void { var a:Number = Number(ti1.text); var b:Number = Number(ti2.text); // Call a method on the module. answer = sm.computeAnswer(a, b).toString(); } ]]> </mx:Script> <mx:Form> <mx:FormHeading label="Enter values to sum."/> <mx:FormItem label="First Number"> <mx:TextInput id="ti1" width="50"/> </mx:FormItem> <mx:FormItem label="Second Number"> <mx:TextInput id="ti2" width="50"/> </mx:FormItem> <mx:FormItem label="Result"> <mx:Label id="ti3" width="100" text="{answer}"/> </mx:FormItem> <mx:Button id="b1" label="Compute" click="addNumbers()"/> </mx:Form> </mx:Application>
在Module模块对象中存取主应用Application
Module模块可以通过其parentApplication属性拿到主应用Application对象的索引,通过这个索引可以访问主应用对象的公共方法和属性。参考以下示例,Module模块文件为,
<?xml version="1.0"?> <!-- modules/ChartChildModule.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" creationComplete="getDataFromParent()"> <mx:Script><![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var expenses:ArrayCollection; // Access properties of the parent application. private function getDataFromParent():void { expenses = parentApplication.expenses; } ]]></mx:Script> <mx:ColumnChart id="myChart" dataProvider="{expenses}"> <mx:horizontalAxis> <mx:CategoryAxis dataProvider="{expenses}" categoryField="Month" /> </mx:horizontalAxis> <mx:series> <mx:ColumnSeries xField="Month" yField="Profit" displayName="Profit" /> <mx:ColumnSeries xField="Month" yField="Expenses" displayName="Expenses" /> </mx:series> </mx:ColumnChart> <mx:Legend dataProvider="{myChart}"/> <mx:Button id="b1" click="expenses = parentApplication.getNewData();" label="Get New Data"/> </mx:Module>
主应用文件为,
<?xml version="1.0"?>
<!-- modules/ChartChildModuleLoader.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script><![CDATA[ import mx.collections.ArrayCollection; [Bindable] public var expenses:ArrayCollection = new ArrayCollection([ {Month:"Jan", Profit:2000, Expenses:1500}, {Month:"Feb", Profit:1000, Expenses:200}, {Month:"Mar", Profit:1500, Expenses:500} ]); public function getNewData():ArrayCollection { return new ArrayCollection([ {Month:"Apr", Profit:1000, Expenses:1100}, {Month:"May", Profit:1300, Expenses:500}, {Month:"Jun", Profit:1200, Expenses:600} ]); } ]]></mx:Script> <mx:ModuleLoader url="ChartChildModule.swf" id="m1"/> </mx:Application>
不过这种方式导致的一个缺点是,自定义的Module模块文件的可移植特性将大打折扣。
在一个Module模块对象中存取另一个Module模块对象
同样地,我们也可以利用ModuleLoader的child属性,在一个Module模块对象中拿到另一个Module模块对象的索引,通过这个索引访问当前Module模块对象的公共方法和属性。参考以下示例,主应用文件,
<?xml version="1.0"?> <!-- modules/TitleModuleLoader.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script><![CDATA[ ]]></mx:Script> <mx:ModuleLoader url="InterModule1.swf" id="m1"/> <mx:ModuleLoader url="InterModule2.swf" id="m2"/> </mx:Application>
Module1文件,
<?xml version="1.0"?> <!-- modules/InterModule1.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"> <mx:Script><![CDATA[ // Defines the method that the other module calls. public function getNewTitle():String { return "New Module Title"; } ]]></mx:Script> </mx:Module>
Module2文件,
<?xml version="1.0"?> <!-- modules/InterModule2.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"> <mx:Script><![CDATA[ [Bindable] private var title:String; // Call method of another module. private function changeTitle():void { title = parentApplication.m1.child.getNewTitle(); } ]]></mx:Script> <mx:HBox> <mx:Label id="l1" text="Title: "/> <mx:Label id="myTitle" text="{title}"/> </mx:HBox> <mx:Button id="b1" label="Change Title" click="changeTitle()"/> </mx:Module>
通过拼ModuleLoader的url参数方式实现数据传输
在url上面拼GET参数基本上是这种格式,url=module1.swf?param1=value1¶m2=value2
比如在主应用文件Application中拼一系列GET参数到ModuleLoader的url属性上,在Module模块文件中解析并处理这些参数,参考以下示例,主应用文件,
<?xml version="1.0"?> <!-- modules/QueryStringApp.mxml --> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" height="500" width="400"> <mx:Script><![CDATA[ public function initModule():void { // Build query string so that it looks something like this: // "QueryStringModule.swf?firstName=Nick&lastName=Danger" var s:String = "QueryStringModule.swf?" + "firstName=" + ti1.text + "&lastName=" + ti2.text; // Changing the url property of the ModuleLoader causes // the ModuleLoader to load a new module. m1.url = s; } ]]></mx:Script> <mx:Form> <mx:FormItem id="fi1" label="First Name:"> <mx:TextInput id="ti1"/> </mx:FormItem> <mx:FormItem id="fi2" label="Last Name:"> <mx:TextInput id="ti2"/> </mx:FormItem> </mx:Form> <mx:ModuleLoader id="m1"/> <mx:Button id="b1" label="Submit" click="initModule()"/> </mx:Application>
模块文件,
<?xml version="1.0"?> <!-- modules/QueryStringModule.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="parseString()"> <mx:Script> <![CDATA[ import mx.utils.*; [Bindable] private var salutation:String; public var o:Object = {}; public function parseString():void { try { // Remove everything before the question mark, including // the question mark. var myPattern:RegExp = /.*\?/; var s:String = this.loaderInfo.url.toString(); s = s.replace(myPattern, ""); // Create an Array of name=value Strings. var params:Array = s.split("&"); // Print the params that are in the Array. var keyStr:String; var valueStr:String; var paramObj:Object = params; for (keyStr in paramObj) { valueStr = String(paramObj[keyStr]); ta1.text += keyStr + ":" + valueStr + "\n"; } // Set the values of the salutation. for (var i:int = 0; i < params.length; i++) { var tempA:Array = params[i].split("="); if (tempA[0] == "firstName") { o.firstName = tempA[1]; } if (tempA[0] == "lastName") { o.lastName = tempA[1]; } } if (StringUtil.trim(o.firstName) != "" && StringUtil.trim(o.lastName) != "") { salutation = "Welcome " + o.firstName + " " + o.lastName + "!"; } else { salutation = "Full name not entered." } } catch (e:Error) { trace(e); } // Show some of the information available through loaderInfo: trace("AS version: " + this.loaderInfo.actionScriptVersion); trace("App height: " + this.loaderInfo.height); trace("App width: " + this.loaderInfo.width); trace("App bytes: " + this.loaderInfo.bytesTotal); } ]]> </mx:Script> <mx:Label text="{salutation}"/> <mx:TextArea height="100" width="300" id="ta1"/> </mx:Module>
利用ActionScript接口实现Module模块间的数据通信
在面向对象的编程中,我们讲要面向接口编程。面向接口的编程方式从一定程度上解决了相互关联的模块间的紧密耦合问题。以上提到的所有数据传输和共享方式都在不同程度上导致了模块间的紧耦合。不过,Flex提供了一种利用标准的ActionScript接口实现Module模块间数据通信的方式。具体地说,对于Module模块对象和主应用Application对象间的通信,我们可以定义一个ActionScript接口,Module模块对象实现了这个接口中定义的方法和属性,那么主应用Application就可以访问这个接口中定义的属性和方法。接口中定义了Module模块对象和主应用Application需要共享的数据和方法,是两者间共同的一个契约,同时也实现了接口和实现的分离,达到了松耦合的目的。参考以下示例,主应用Application,
<?xml version="1.0"?> <!-- modules/interfaceexample/Main.mxml --> <mx:Application xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import mx.modules.ModuleManager; [Bindable] public var selectedItem:Object; [Bindable] public var currentModuleName:String; private function applyModuleSettings(e:Event):void { // Cast the ModuleLoader's child to the interface. // This child is an instance of the module. // You can now call methods on that instance. var ichild:* = mod.child as IModuleInterface; if (mod.child != null) { // Call setters in the module to adjust its // appearance when it loads. ichild.setAdjusterID(myId.text); ichild.setBackgroundColor(myColor.selectedColor); } else { trace("Uh oh. The mod.child property is null"); } // Set the value of a local variable by calling a method // on the interface. currentModuleName = ichild.getModuleName(); } private function reloadModule():void { mod.unloadModule(); mod.loadModule(); } ]]> </mx:Script> <mx:Form> <mx:FormItem label="Current Module:"> <mx:Label id="l1" text="{currentModuleName}"/> </mx:FormItem> <mx:FormItem label="Adjuster ID:"> <mx:TextInput id="myId" text="Enter your ID"/> </mx:FormItem> <mx:FormItem label="Background Color:"> <mx:ColorPicker id="myColor" selectedColor="0xFFFFFF" change="reloadModule()" /> </mx:FormItem> </mx:Form> <mx:Label text="Long Shot Insurance" fontSize="24"/> <mx:ComboBox labelField="label" close="selectedItem=ComboBox(event.target).selectedItem" > <mx:dataProvider> <mx:Object label="Select Module"/> <mx:Object label="Auto Insurance" module="AutoInsurance.swf"/> </mx:dataProvider> </mx:ComboBox> <mx:Panel width="100%" height="100%"> <mx:ModuleLoader id="mod" width="100%" url="{selectedItem.module}" ready="applyModuleSettings(event)" /> </mx:Panel> <mx:Button id="b1" label="Reload Module" click="reloadModule()"/> </mx:Application>
接口文件,
// modules/interfaceexample/IModuleInterface
package { import flash.events.IEventDispatcher; public interface IModuleInterface extends IEventDispatcher { function getModuleName():String; function setAdjusterID(s:String):void; function setBackgroundColor(n:Number):void; } }
Module模块文件,
<?xml version="1.0"?> <!-- modules/interfaceexample/AutoInsurance.mxml --> <mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" implements="IModuleInterface"> <mx:Panel id="p1" title="Auto Insurance" width="100%" height="100%" backgroundColor="{bgcolor}" > <mx:Label id="myLabel" text="ID: {adjuster}"/> </mx:Panel> <mx:Script> <![CDATA[ [Bindable] private var adjuster:String; [Bindable] private var bgcolor:Number; public function setAdjusterID(s:String):void { adjuster = s; } public function setBackgroundColor(n:Number):void { // Use a bindable property to set values of controls // in the module. This ensures that the property will be set // even if Flex applies the property after the module is // loaded but before it is rendered by the player. bgcolor = n; // Don't do this. The backgroundColor style might not be set // by the time the ModuleLoader triggers the READY // event: // p1.setStyle("backgroundColor", n); } public function getModuleName():String { return "Auto Insurance"; } ]]> </mx:Script> </mx:Module>
发表评论
-
Flex States 视图状态
2010-08-30 23:06 2153Flex States可以为组件定义多个视图状态,每一 ... -
flex中使用链接报告优化Module大小的测试
2010-08-18 20:51 1686最近使用PuerMVC和Module机制构建了一个界面和操作类 ... -
flex ToolTip专题
2010-06-03 12:46 46091 创建ToolTips 每一个可视化的Flex组件 ... -
pureMVC使用经验和建议
2010-06-03 11:00 1462下面是有经验的朋友分 ... -
pureMVC框架及其开发
2010-06-03 10:46 1155PureMVC框架的目标很明确 ... -
HTML页面加载和解析流程
2010-04-21 11:38 28361.用户输入网址(假设是个html页面,并且是第一次访问),浏 ... -
CSS参考手册
2010-04-21 11:02 882颜色与背景 •color •background-colo ... -
HTML参考手册( 标签、属性和事件)
2010-04-20 17:17 1518HTML标签 标签 描述 DTD <!--...- ... -
flex itemRenderer使用(五):效率
2010-04-17 17:01 1205如果您要显示大量 itemRe ... -
flex itemRenderer使用(四):状态和过渡
2010-04-17 16:01 1748itemRenderer 最擅长与应用程序的用户通信。有时通信 ... -
flex itemRenderer使用(三):通信
2010-04-17 14:51 1556在本系列的第 2 部分中, 我向您展示了如何使用 MXML 和 ... -
flex处理XML(一)基础
2010-04-15 15:24 1308FLEX处理XML,ECMAScript For XML(e4 ... -
flex itemRenderer使用(二)外部渲染器
2010-04-09 18:18 1592在本系列的第 1 部分中, 我向您展示了如何创建内联 item ... -
flex itemRenderer使用(一)内联渲染器
2010-04-09 17:50 1459Flex 提供许多控制, 它们 ... -
Flex Metadata Tag高级应用
2010-04-01 14:42 2372原文地址:http://livedocs. ... -
Flex Metadata Tag归纳总结
2010-04-01 14:25 1045Flex引入了元数据标签的概念,它告诉编译器如何编译这段 ... -
Flex和JS通信
2010-03-06 18:42 1743flex提供了和JS通信的方法,使用flexSDK中的Exte ... -
最近完成的某系统的报表组件
2010-01-20 21:12 2566最近做完了一个flex+java的项目,其中项目的主要特 ... -
Flex Chart组件的阴影去除
2009-12-21 10:52 2115去除Flex Chart组件的阴影有多种方法,最简单最直接的方 ... -
flex中==和===的区别(和java的==和equals类似但也有不同之处)
2009-12-21 09:44 4731===用于测试两个表达式 ...
相关推荐
Flex Module间通信 此例给大家展示一个使用了模块(Module)的简单的Flex程序,你可以从中获得启示。
不要以为我要5分很高,这个绝对是官网资源,其中包含各位最一直在寻找却找不到即使找到也不好用的 flex-bootstrap-jsp.jar flex-bootstrap.jar flex-webtier-jsp.jar flex-webtier.jar
FlexModule_j2ee Flex 与JSP 整合用的.jar 文件 Jsp 中引用Flex 标签
the Flex 3 compiler module for J2EE application servers.
通过这个工程可以实现flex页面嵌入到jsp中。
Flex基于Module模块的开发文档主要介绍涵盖基本所有: 1、模块化的定义与原理; 2、模块化的作用; 3、模块化的优点; 4、flex与模块通信,直接调用模块(module)方法及示例代码; 5、flex基本控件用法及示例代码;...
flex中文基础教程,适合初学者
在Flex工程中添加Module的方法是:在FlashBuilder中右键工程目录->Porperties->Flex Modules, 然后就可以add/edit/remove需要的module了, 但问题 是无论添加多少module都要点击add按钮一个一个添加! 像我们的项目一...
来自ITEYE,具体是哪位的分享记不得了- - 里头的demo详细演示了flex module的使用和flex module的通讯
flex教程 Flex中文基础教程Flex中文基础教程Flex中文基础教程
在Flex3的Module模块程序设计中,在Google中进行了大量的资料查找,综合比较各个资源后,将我认为最有价值的资料放在这里(全英文的)。 下载包中包括: 1、Adobe Creating Mudule Application.pdf 2、相似例子的源...
一个有关 flex module 讲解的详细ppt
Flex3开发指南 flex3基础教程
the Flex 3 compiler module for J2EE application servers.
Flex基础教程Flex基础教程Flex基础教程Flex基础教程Flex基础教程Flex基础教程Flex基础教程Flex基础教程
Flex技术基础培训 2003版 Flex技术基础培训 2003版
关于Flex的入门基础资料,详细介绍了Flex的开发,是一部难得的Flex教程