Flex的背景和技术特点

http://www.webjx.com/  2008-12-17 15:06:44  来源:蓝色理想 

Webjx核心提示:本章内容介绍Flex的背景和技术特点,并通过示例程序来展示Flex的界面效果和技术内涵.

 

1.4  ActionScript

ActionScript是为Adobe Flash设计的面向对象的程序设计语言,在Flex开发中,ActionScript的基本作用类似于传统网页开发中的JavaScript,同时ActionScript还要负责Flex程序的逻辑控制和业务建模。ActionScript遵循欧洲计算机制造商协会(ECMA)通过的ECMAScript标准,而ECMAScript出自JavaScript派生出的标准ECMA-262,因此无论是使用语法还是技巧方面,ActionScript与JavaScript都非常相似。

作为Flex技术的组成部分,ActionScript充当着更加重要的角色。如果说MXML是Flex亮丽的外表,那么ActionScipt就赋予了Flex聪慧的灵魂。对于开发者而言,在ActionScript上所下的功夫要大于MXML,MXML作为界面表现层需要更多的是外观设计,而ActionScript则需要担当起用户交互、数据处理和业务逻辑处理的重任。不仅如此,在MXML中所使用的Panel、Label等Flex内建组件都是基于ActionScript类实现的,应用ActionScript可以继承这些内建的组件对象来创建自定义的Flex组件,使得开发的灵活性大大增加。ActionScript的应用还可以涉及到表现层数据模型以及异步远程请求及响应的事务处理。

我们可以通过<mx:Script>标签在MXML文件中插入ActionScript代码或导入ActionScript类文件。而在编译过程中,ActionScript代码和MXML代码都会被分离成ActionScript类,最终编译器连接所有的ActionScript类,编译生成SWF文件。

1.4.1  在MXML中使用ActionScript脚本

MXML使用<mx:Script>标签实现对ActionScript的内部编译支持,因此,ActionScript脚本代码可直接在标签内编写,此时ActionScript以方法为基本单位独立作用,可在MXML代码中直接调用。这里需要注意的是,MXML内部嵌入ActionScript代码的方式并非使用了单独的编译机制,在MXML进行编译的过程中,内部的ActionScript代码会被抽取出去并创建独立的ActionScript类文件,最后组合到SWF文件之中。

下面来看一看在MXML内部使用ActionScript的示例程序。

示例1.2  使用ActionScript脚本

<?xml version="1.0" encoding="utf-8"?>
<!--此示例程序中要使用中文,因此进行编码声明,请注意保存时选择正确的编码-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function changeText():void {
    disp1.text = "使用ActionScript";
}
]]>
</mx:Script>
<mx:Panel title="Flex ActionScript Test" paddingTop="10" paddingBottom="10"
  paddingLeft="10" paddingRight="10" x="10" y="10" fontSize="12">
<mx:Label id="disp1" text="Hello World. 世界,你好!" fontWeight="normal"
fontSize="24" fontFamily="Times New Roman" fontStyle="italic"
alpha="1.0"/>
<mx:Button label="点击这里"  fontSize="16" click="changeText()"/>
</mx:Panel>
</mx:Application>

示例1.2的程序基本是对上一个HelloWorld示例的扩充,我们对Label添加了一个id属性,并在<mx:Script>中对这个id进行引用,请特别注意<mx:Script>标签在MXML中的引用方式,其内容为ActionScript代码,因此要用<![CDATA[  ]]>括起来保证对其作为一个字符内容的引用,否则ActionScript代码中的操作符很容易与XML的关键字发生冲突,如<、>、&等符号在XML中都有特定的意义。

下面来看看这个示例的运行效果。

如图1.3所示,这次运行的效果多了一个按钮组件,即代码中的<mx:Button>,并且我们设置了按钮组件的click属性,即设置了按钮的单击触发为执行ActionScript方法changeText(),接下来可以单击按钮查看效果,结果如图1.4所示。

图1.3  ActionScript测试运行效果一

图1.4  ActionScript测试运行效果二

在图1.4中,Label的文字内容被替换成为字符串“使用ActionScript”。我们可以看到ActionScript代码中changeText()方法的作用是,响应一个按钮单击事件,通过属性id引用MXML的界面组件,并通过用户交互来处理组件的变化,这是ActionScript最常见的应用方法。本示例中,通过changeText()方法对id为disp1的Label组件进行text赋值操作,通过这个示例我们可以熟悉一下ActionScript的一些语法规则,public function changeText():void是ActionScript的方法定义,访问控制字为public,而function是方法定义关键字,方法名称为changeText,返回值类型为void。在MXML代码中直接嵌入ActionScript时不需要设计ActionScript类,直接以方法作为执行单位。

如果是简单的事件响应处理,如输入校验、组件可见性控制等处理,那么用上面的方法还没有问题,但如果需要对数据进行复杂的逻辑操作或者需要对MXML的组件进行定制操作,就需要ActionScript类来完成了。

1.4.2  使用ActionScript类

在上面的示例中,我们把ActionScript代码嵌入到MXML中使用,如果大量的程序脚本都集中在MXML文件内,会给开发和维护都会带来极大的不便,因此在开发时要注意尽量将ActionScript代码从MXML文件中分离出去。

对ActionScript代码进行分离的最简单方法也是通过<mx:Script>标签来实现,需要设置<mx:Script>标签的source属性。例如我们的ActionScript文件是includes文件夹下的tools.as,那么可以通过<mx:Script source=“includes/tools.as”>来实现对ActionScript文件的引入,这样ActionScript的代码部分可以从MXML中分离出去。

但是仅仅用上述方式分离代码还是不够的,这种方式仅仅在书写上将ActionScript代码单独分离出去,与HTML中引入JavaScript的方式是完全一致的,而文件对实际的程序设计和代码维护并没有起到作用,因此使用<mx:Script>的source属性容易造成误区,导致ActionScript的滥用。对于规模较小或逻辑很清晰的RIA应用,仅使用ActionScript方法就可以满足大部分要求,而对于一个较大的软件项目或者比较复杂的RIA应用,必须对ActionScript类进行设计。

ActoinScript是面向对象的程序设计语言,而类是面向对象程序设计语言的精髓。面向对象的特性(封装、继承和多态)都被ActionScript很好地支持。使用ActionScript进行开发时,可以使用所有的面向对象特性。

在SDK的功能支持上提供了完善的API,使用ActionScript类可以实现系统的所有逻辑操作和数据模型处理,实现对系统的分层开发,同时也用于进行企业级模块的构建;对于界面开发,可以使用ActionScript类对现有的MXML类继承并进行定制化开发,也可以在组件操作上实现自定义的功能。

ActionScript使用包(Package)对类进行组织,定义一个包的同时,相当于隐含规定了一个命名空间,可以很好地解决类的组织问题。不同的包下可以放置同名的ActionScript类,在不同的包中调用类需要用Import语句来导入,因此可以很好地避免同名类的冲突问题。对于类文件在计算机中的物理位置—— 需要用与包名称相对应的文件夹名来存放,如net.airdev.book这样一个包下的类文件,应该在net\airdev\book\这样的文件夹路径之下进行保存,包结构与文件结构完全对应。有Java开发背景的开发者对包肯定不会陌生,ActionScript中包的使用与Java中是基本一致的。

下面对一个以Flex实现的四则运算计算器程序进行结构设计,并在程序中实现一个自定义组件,程序设计类图如图1.5所示。

图1.5  Calculator程序设计类图

我们把MXML文件视为一个控制表现层的类Class4MXML,在MXML中要建立输入框、计算方法选择按钮和计算按钮,其中计算按钮使用一个继承自Button的自定义组件MyButton。

程序需要负责计算的功能模块,因此我们设计一个Calculator类,这个类提供一个计算方法run,该方法需要三个参数,两个操作数arg1、arg2和一个计算方法标记method。

代码文件夹结构如下:

C:\user\test.mxml
C:\user\myControls\Calculator.as
C:\user\myControls\MyButton.as

示例1.3a  计算器应用程序的MXML代码

<!--Test.mxml-->
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx=http://www.adobe.com/2006/mxml xmlns:cmp= "myControls.*" >
<!--声明一个名为cmp的命名空间,以此来引用myControls包中的自定义组件-->
<mx:Script>
<![CDATA[
import myControls.*;
//通过import命令导入myControls包中的类
var calcul = new Calculator();
//实例化一个Calculator类
]]>
</mx:Script>
<mx:Panel title="Flex ActionScript Test" paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" layout="absolute" height="180" width="304">
<!--把Panel的layout属性设置为absolute,从而对这个Panel上的组件进行坐标定位-->
<mx:Label id="ta1" text="Calculator Test" fontWeight="bold" fontSize="16" width="250" height="30" x="10" y="10"/>
<mx:TextInput id="n1" width="77" x="10" y="46"/>
<mx:TextInput id="n2" width="77" x="198" y="46"/>
<mx:TextInput id="res" width="77" x="74" y="99" enabled="false"/>
<!--设置输入和输出所需要的TextInput组件-->
<cmp:MyButton click="res.text=calcul.run(Number(n1.text), Number(n2.text),tp.value).toString()" x="196.5" y="99"/>
<!--配置一个自定义组件MyButton,并设定该组件的单击事件执行calc1的run方法,并将结果转换成String类型,显示在id为res的TexInput组件上-->
<mx:Label x="47.5" y="101" text="=" width="18"/>
<mx:ComboBox id="tp" x="112" y="46" width="60">
<mx:dataProvider>
<mx:Array>
<mx:Object label="+" data="0" />
<mx:Object label="-" data="1" />
<mx:Object label="*" data="2" />
<mx:Object label="/" data="3" />
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
<!--配置可选择的操作符,支持四则运算-->
</mx:Panel>
</mx:Application>

这个MXML的编写方法与前面的示例基本一致,只是增加了命名空间以支持自定义组件Mybutton的使用,并对各个组件的定位进行了一些坐标控制。

示例1.3b  计算器应用程序的ActionScript代码

//Calculator.as
package myControls {
//包声明
public class Calculator {
//类声明
public function run(a:Number,b:Number,c:Number):Number {
//函数声明。变量a和b为操作数,变量c为计算类型
var res:Number;
//计算结果通过res变量返回
if(c==0){
res = a + b;
}
else if(c==1){
res = a - b;
}
else if(c==2){
res = a * b;
}
else if(c==3){
res = a / b;
}
return res;
}
}
}
//MyButton.as
package myControls {
import mx.controls.Button;
import flash.events.MouseEvent;
import mx.controls.Label;
public class MyButton extends Button {
public function MyButton() {
this.label = "GO";
this.setActualSize(100, 30);
}
}
}

示例1.3的程序由以上3个程序文件组成,text.mxml为表现层,在MXML初始化时创建了一个Calculator的实例;Calculator.as和MyButton.as 分别对应两个功能模型,Calculator类提供了一个计算器方法,而MyButton类则继承了MXML的标准组件Button类,本程序中的自定义组件仅仅是在组件构造方法中实现了对label属性和定位的初始化,在实际应用过程中,对组件类的继承可以进行更复杂的定制化操作。

程序运行效果如图1.6所示。

图1.6  Calculator程序的运行效果

更多