7.2.3 使用ActionScript组件
Flex的核心
Flex的核心是MXML和ActionScript 。
MXML用于为属于表示层的Flex应用程序制作UI布局,并通过编辑到ActionScript并生成ActionScript类文件最终在Flash Player上运行。 如果您是一位Java开发人员并且可以理解这一点,那么MXML就像JSP / Struts / JSF一样,最终将被编译为Java类,并在具有JAVA虚拟机环境的浏览器上运行。
所以,ActionScript仍然是Flex的核心。 在Flex中,ActionScript是一个包含组件(容器和控件),管理器类,数据服务类和所有其他函数的类的类库。
ActionScript常用的三种方式
1.内联方式
<mx:Button label="Say Hello" click="mx.controls.Alert.show('Hello,Flying')"/>
2.级联方式
<mx:Button label="Say Hello" click="sayHello('Flying')"/>
<mx:Script>
<![CDATA[ import mx.controls.Alert; private function sayHello(param_name:String):void { Alert.show("Hello, "+param_name); } ]]> </mx:Script>
3.外联方式
<mx:Script source="myFunction.as"/>
<mx:Button label="Say Hello" click="sayHello('Flying');"/>
// myFunction.asimport mx.controls.Alert; private function sayHello(param_name:String):void { mx.controls.Alert.show("Hello, "+param_name); }
上面的方法为用ActionScript创建一个新的单独的ascf文件,然后为Script元素的源属性值调用元素设置方法,并且可以在方法中传入参数,这个文件可以在多个文件中调用, 以实现ActionScript方法在多个文件中的重用。
下面讲讲ActionScript构建组件
您可以使用ActionScript来创建一个可重用组件,该组件可以在您的Flex应用程序中作为标签引用。在ActionScript中创建的组件可以包含图像元素,自定义业务逻辑,甚至可以扩展现有的Flex组件。 在ActionScript中,Flex组件实现了类层次结构。每个组件都是Action类的一个实例。
所有Flex可视组件都是从UIComponent类派生的。要创建自己的组件,可以创建一个继承UIComponent或UIComponent子类的类。 将类用作自定义组件的超类取决于您想要实现的内容。例如,您可能需要一个自定义按钮控件。您可以创建UIComponent类的子类,然后覆盖Flex Button类的所有功能。创建自定义按钮构建的更好方法是创建Flex按钮组件的子类并在自定义类中对其进行修改。 下面的代码贴出来[注:一切从可重用性考虑,否则不需要构建组件],仅供参考
PaddedPanel.as
<SPAN style="FONT-SIZE: large">package components
{
import mx.containers.Panel;
public class PaddedPanel extends Panel
{
public function PaddedPanel()
{
// Call the constructor of the superclass.
super();
// Give the panel a uniform 10-pixel
// padding on all four sides.
setStyle("paddingLeft", 10);
setStyle("paddingRight", 10);
setStyle("paddingTop", 10);
setStyle("paddingBottom", 10);
}
}
}</SPAN>
NumericDisplay.as
<SPAN style="FONT-SIZE: large">package components
{
import flash.events.Event;
import flash.events.MouseEvent;
import mx.containers.Tile;
import mx.containers.VBox;
import mx.controls.Button;
import mx.controls.TextInput;
import mx.events.FlexEvent;
public class NumericDisplay extends VBox
{
private var display:TextInput;
private var buttonsTile:Tile;
// Expose the _numButtons property to the
// visual design view in Flex Builder 3.
[Inspectable(defaultValue=10)]
private var _numButtons:uint = 10;
//原来主应用程序中的引用本类的组件属性是取决于改自定义组件类是否定了了set方法而已,当然属性名称与set方法名称一致
private var _max:int=90;
public function set max(v:int):void{
}
public function get max():int{
return _max;
}
public function NumericDisplay()
{
addEventListener(FlexEvent.INITIALIZE, initializeHandler);
}
// numButtons is a public property that determines the
// number of buttons that is displayed
[Bindable(event="numButtonsChange")]
public function get numButtons():uint
{
return _numButtons;
}// //当numButtons被赋值时,发出numButtonsChanage事件,通知所有被绑定的getter方法执行一遍
public function set numButtons(value:uint):void
{
_numButtons = value;
dispatchEvent(new Event("numButtonsChange"));
}
// Gets called when the component has been initialized
private function initializeHandler(event:FlexEvent):void
{
// Display the component
paint();
}
// Add the label of the clicked button to the display
private function buttonClickHandler(event:MouseEvent):void
{
display.text += (event.target as Button).label;
}
// Display the component
private function paint():void
{
// Create the number display
display = new TextInput();
display.width=185;
addChild(display);
// Create a Tile container to
// hold the buttons.
buttonsTile = new Tile();
addChild (buttonsTile);
// Create the buttons and add them to
// the Tile container.
for (var i:uint = 0; i < _numButtons; i++)
{
var currentButton:Button = new Button();
currentButton.label = i.toString();
currentButton.addEventListener(MouseEvent.CLICK, buttonClickHandler);
buttonsTile.addChild (currentButton);
}
}
}
}</SPAN>
CountryComboBox.as
<span style="font-size: large;">package components
{
import mx.controls.ComboBox;
import flash.events.Event;
public class CountryComboBox extends ComboBox
{
private var countryArrayShort:Array = ["US", "UK"];
private var countryArrayLong:Array = ["United States", "United Kingdom"];
// Determines display state. The inspectable metadata tag
// is used by Flex Builder 3.
[Inspectable(defaultValue=true)]
private var _useShortNames:Boolean = true;
// Implicit setter
public function set useShortNames(state:Boolean):void
{
// Call method to set the dataProvider based on the name length.
_useShortNames = state;
if (state)
{
this.dataProvider = countryArrayShort;
}
else
{
this.dataProvider = countryArrayLong;
}
// Dispatch an event when the value changes
// (used in data binding).
dispatchEvent(new Event("changeUseShortNames"));
}
// Allow other components to bind to this property
[Bindable(event="changeUseShortNames")]
public function get useShortNames():Boolean
{
return _useShortNames;
}
}
}</span>
主应用程序mxml
<?xml version="1.0" encoding="utf-8"?>
<SPAN style="FONT-SIZE: large"><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"
xmlns:components="components.*">
<s:layout>
<s:BasicLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import flash.events.Event;
private function handleCloseEvent(eventObj:Event):void
{
status.text = "You selected: \r" + countries.selectedItem as String;
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
</fx:Declarations>
<components:PaddedPanel
title="Custom component inheritance"
>
<components:CountryComboBox
id="countries"
useShortNames="false"
/>
<!--
Use data binding to display the latest state
of the property.
-->
<mx:Label text="useShortNames = {countries.useShortNames}"/>
<mx:ControlBar horizontalAlign="right">
<mx:Button
label="Toggle Display"
click="countries.useShortNames = !countries.useShortNames;"
/>
<mx:Text id="status" text="Please select a country from the list above." width="136"/>
<components:NumericDisplay numButtons="10" />
</mx:ControlBar>
</components:PaddedPanel>
</s:Application>
</SPAN>
灵活创建自定义组件
使用ActionScript组件的一般目的是创建可配置和可重用的组件。例如,创建一个具有属性,可分配时间,定义新样式,具有自定义外观或其他个人设置的ActionScript组件。
创建自定义ActionScript组件时的设计注意事项之一是可重用性。换句话说,是否要创建一个紧密绑定的组件,它将是某个应用程序的紧密耦合组件,还是它可以在多个应用程序中重用的组件?
编写与特定应用程序紧密耦合的组件通常是依赖于应用程序的结构,变量名称或其他细节的组件。如果更改应用程序,则可能需要修改紧密耦合的组件以反映此更改。一个紧密耦合的组件,可能很难适用于其他应用程序而无需重写。
松散耦合
设计一个松散耦合的组件以供重用。松散耦合的组件需要有明确可辨识的接口,指定如何将信息传递给组件,以及如何将结果传递回应用程序。
典型的松散耦合组件使用属性将信息传递给组件。这些属性由缺省访问器(setter和getter方法)定义,指定参数的类型。在下面的示例中,CountryComboBox自定义组件定义了一个公共的userShortNames属性,该属性通过使用get userShortNames()和set useShortNames()访问器方法来公开私有属性_userShortNames。
私有属性_userShortNames的Inspectable元数据标记定义了属性,该属性显示在Adobe®Flex Builder的属性提示,并标记在内在函数中。您也可以使用此元数据标记来限制允许的属性值。
注意:所有公共属性都出现在MXML的代码提示和属性检查器中。如果您有关于可以帮助阅读的代码提示或属性检查器的属性的附加信息(如枚举值,或者一些实际上是文件路径的字符串),那么附加信息也会添加到[Inspectable]元素Data中。
利用代码提示和属性检查器
MXML代码提示和属性检查器来自相同的数据,所以如果显示一个,那么另一个应该也是显示状态。
另一方面,如果ActionScript代码暗示元数据不起作用,您可以随时在ActionScript中看到相应的代码提示,具体内容取决于您所处的上下文。 Flex Builder使用ActionScript代码提示,例如public / protected / private / static修饰符加上当前范围。
定义组件以将信息返回给主应用程序的最佳实践是设计包含要返回的数据的组件分发事件。这样,主函数可以定义时间监听器来处理时间并采取适当的行动。你也可以在事件中使用数据绑定。比如,绑定属性使用Bindable元数据标签userShortName进行编程。隐式的userShortName属性设置器发送更改事件,此过程使用Flex框架的内部机制来使数据绑定正常工作。