1. 模块化的定义与原理
1.1 模块化的定义
模块是包含了一个IFlexModuleFactory类工厂的可动态加载的特殊类型的swf,它允许一个程序在运行时加载代码并创建类实例。
1.2 模块化的原理
Flex应用程序是以swf形式发布的。Swf形式的文件分为两种类型,如下表所示:
类型 | 特征 | 特点 |
Application | 最外层容器以<s:Application…>开头 | 可以单独执行 |
Module | 最外层容器以<mx:Module…>开头 | 不可以单独执行,必须被ModuleLoader组件加载后才能执行 |
在完全采用Flex作为客户端技术的web系统中,由上述的Application和Module构成全部界面。
2 模块化的作用
1) Flex模块化可分离应用程序代码到不同的swf文件上以减少加载时间和文件大小。
2) 多界面效果
在Flex技术中,通过模块化实现多界面效果,每个界面对应一个Flex模块。通常需要定义一个Application类型的界面作为主界面,在其上定义子界面的容器(ModuleLoader组件)。然后定义多个Module类型的子界面,在主界面的ModuleLoader组件中,动态加载Module类型的子界面以实现多界面切换。
3 模块化的优点
使用模块化开发有如下优点:
1. 主应用程序开始时不需要马上下载模块,应用程序会根据需求载入和卸载模块。
2. 由于每个模块独立于其他应用程序模块,当需要改变一个模块时,只需要重编译这个模块而不是整个应用程序。
代码
我的这个程序是由左边的树形菜单和中间的内容页面组成。根据点击菜单选项动态加载内容页面(菜单和内容都是module)
为了主程序能得到菜单module里点击的是什么选项module里implement一个事件接口。点击菜单是派发事件,主界面监听到事件后调用接口中的get方法获取数据。
应为module实现了接口,这样主程序直接到接口文件中调get方法就行了而不是调用module里的get方法。应为直接调用module的get的话 module会被编译到主程序中,module减少application体积的作用就废了
接口文件:
package
{
import flash.events.IEventDispatcher;
public interface ISideNavigate extends IEventDispatcher
{
function getContentUrl():String;
}
}
Module文件:implements="ISideNavigate"实现接口:public function getContentUrl():
<?xml version="1.0" encoding="utf-8"?>
<s:Module xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
implements="ISideNavigate"
creationComplete="appInit(event)">
<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";
mx|Tree{
/* these two styles make the tree lines look better */
padding-top: 10; /* default is 2 */
padding-bottom: 0; /* default is 2 */
contentBackgroundColor:#BEE2E9;
fontSize:20;
fontWeight:bold;
leading:7
}
</fx:Style>
<fx:Metadata>
[Event(name="DeptOption", type="flash.events.Event")]
</fx:Metadata>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.events.ListEvent;
[Bindable]
public var selectedNode:XML;
public var contentUrl:String=null;
/* 初始化的时候将Tree展开 */
protected function appInit(event:FlexEvent):void
{
deptTree.selectedIndex=1;
var node:XML=deptTree.selectedItem as XML;
deptTree.expandItem(node,!deptTree.isItemOpen(node),true);
}
/* 获取点击deptTree选择的项 */
protected function deptTree_changeHandler(event:ListEvent):void
{
selectedNode=Tree(event.target).selectedItem as XML;
//selectedNode=deptTree.selectedItem as XML;
contentUrl=selectedNode.@label;
dispatchEvent(new Event("DeptOption"));
}
/* 双击展开 */
protected function deptTree_itemDoubleClickHandler(event:ListEvent):void
{
var node:XML=deptTree.selectedItem as XML;
deptTree.expandItem(node,!deptTree.isItemOpen(node),true);
}
/* 实现接口中的get方法 */
public function getContentUrl():String{
return this.contentUrl;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<fx:XML id="deptTreeData">
<root label="部门导航">
<node label="营销部"/>
<node label="财务"/>
<node label="人力资源部"/>
<node label="行政部"/>
<node label="客服部"/>
</root>
</fx:XML>
</fx:Declarations>
<!--Tree默认doubleClickEnabled为false-->
<mx:Tree id="deptTree" width="{parentApplication.width/7}" height="{parentApplication.height}"
change="deptTree_changeHandler(event)"
doubleClickEnabled="true"
itemDoubleClick="deptTree_itemDoubleClickHandler(event)"
dataProvider="{deptTreeData}" labelField="@label" />
<!--<s:Label id="myTxt" x="395" y="158" text="选择了部门:{selectedNode.@label}"/>-->
</s:Module>
applicantion 文件:
<mx:ModuleLoader id="leftModuleLoader"
loadLeftModule("Module/DeptTree.swf");加载模块
sideModuleLoader_readyHandler 监听加载模块里的点击事件
<?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/mx" minWidth="955" minHeight="600"
initialize="appInit(event)">
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<mx:ModuleLoader id="leftModuleLoader" error="ModuleLoader_errorHandler(event)"
ready="sideModuleLoader_readyHandler(event)"
y="30" width="20%" height="100%" left="0"/>
<mx:ModuleLoader id="contentModuleLoader" error="ModuleLoader_errorHandler(event)"
y="230" width="60%" horizontalCenter="0"/>
<mx:ModuleLoader id="rightModuleLoader" error="ModuleLoader_errorHandler(event)"
ready="sideModuleLoader_readyHandler(event)"
y="30" width="20%" height="100%" right="0"/>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.events.ModuleEvent;
private var ILeftNavagetModule:ISideNavigate; //左菜单
private var IRightNavagetModule:ISideNavigate;//右菜单
protected function appInit(event:FlexEvent):void
{
loadLeftModule("Module/DeptTree.swf");
loadRightModule("Module/FunctionOptionTree.swf");
//loadContentModule(contentUrl);
}
private function loadLeftModule(Url:String):void{
if(leftModuleLoader.url==Url)
return;
if(leftModuleLoader.url !=null)
leftModuleLoader.unloadModule();
leftModuleLoader.url=Url;
}
private function loadRightModule(Url:String):void{
if(rightModuleLoader.url==Url)
return;
if(rightModuleLoader.url !=null)
rightModuleLoader.unloadModule();
rightModuleLoader.url=Url;
}
private function loadContentModule(Url:String):void{
/* if(contentModuleLoader.url==Url)
return;
if(contentModuleLoader.url !=null)
contentModuleLoader.unloadModule();
contentModuleLoader.url=Url; */
}
protected function ModuleLoader_errorHandler(event:ModuleEvent):void
{
var erroInfo:String=event.target.id;
Alert.show("对不起"+erroInfo+"加载错误");
}
protected function sideModuleLoader_readyHandler(event:ModuleEvent):void
{
//监听左侧导航栏点击按钮事件,获得导航按钮选择的模块地址传给loadContentModule加载模块
ILeftNavagetModule=leftModuleLoader.child as ISideNavigate;//赋值给接口
ILeftNavagetModule.addEventListener('DeptOption',
function():void{
loadContentModule(ILeftNavagetModule.getContentUrl());
Alert.show(ILeftNavagetModule.getContentUrl());
});
IRightNavagetModule=rightModuleLoader.child as ISideNavigate;//赋值给接口
IRightNavagetModule.addEventListener('FunctionOption',
function():void{
//loadContentModule(ISideNavagetModule.getContentUrl());
Alert.show(IRightNavagetModule.getContentUrl(),"message");
});
}
]]>
</fx:Script>
</s:Application>