当你在没有添加事件设置的情形下使用 Bindable 标记时,propertyChange 是将被下发的默认事件类型。 因此,[Bindable] 标记等同于Bindable(event="propertyChange")。 当你没有指定事件字符串时,编译器将为 setter 和 getter 函数创建附加代码,因此建议你添加自己的名称常量以避免产生这种额外的开销。
请看下面绑定语句:
[Bindable]
public var testData:String;
由于没有设置事件名称,编译器将创建下列代码:
[Bindable(event="propertyChange")]
public function get testData():String
{
return this._1147269284testData;
}
public function set testData(value:String):void
{
var oldValue:Object = this._1147269284testData;
if (oldValue !== value) {
this._1147269284testData = value;
if (this.hasEventListener("propertyChange"))
this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent
(this, "testData", oldValue, value));
}
}
正如你看到的那样,mxmlc 创建一个合成 setter 函数,该函数包含发送PropertyChangeEvent 事件的代码。当你更改默认常数,Flex 编译器将不会生成代码,并且你自己应该负责发送该事件。这样,你可以优化侦听代码。如果你没有更改默认常数,则每个 [Bindable] 属性将会发送propertyChange 事件,并且侦听代码必须查询该事件以便确定哪个属性已经更改。如果一个类具有大量的 [Bindable] 属性,则这是一个代价非常高的过程。
一旦你自己设置了事件名称(如下面范例所示),则编译器将会复制该代码。
public static const EVENT_CHANGED_CONST:String = "eventChangedConst"; private var _number:Number = 0; [Bindable(event=EVENT_CHANGED_CONST)] public function get number():Number { return _number; } public function set number(value:Number) : void { _number = value; dispatchEvent(new Event(EVENT_CHANGED_CONST)); }
使用 [Bindable] 标记中的错误事件名称将会导致你的应用程序不能绑定你的属性,而且你甚至还不知道为什么。当你使用具有客户名称的[Bindable] 标记时,下面的范例似乎是个很好的主意:
public static const EVENT_CHANGED_CONST:String = "eventChangedConst";
private var _number:Number = 0;
[Bindable(event=EVENT_CHANGED_CONST)]
public function get number():Number
{
return _number;
}
public function set number(value:Number) : void
{
_number = value;
dispatchEvent(new Event(EVENT_CHANGED_CONST));
}
上面的代码将一个静态属性赋给事件名称,然后使用相同的赋值发送该事件。然而,当该值更改时,绑定功能似乎不能工作。其原因是该事件的名称将是EVENT_CHANGED_CONST 而不是该变量的值。
你的代码应该如下所示:
public static const EVENT_CHANGED_CONST:String = "eventChangedConst"; private var _number:Number = 0; [Bindable(event="eventChangedConst")] public function get number():Number { return _number; } public function set number(value:Number) : void { _number = value; dispatchEvent(new Event(EVENT_CHANGED_CONST)); }
绑定的一个常见的错误是假定绑定是以同步的执行顺序发生的。这将会导致你的应用程序产生告警并且不能绑定你的属性。实际上,ActionScript的事件是以异步的方式执行的。
查看下面的代码范例:
<?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="1024" minHeight="768"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
[Bindable]
public var buttonText:String = "Execution order mistake ";
]]>
</fx:Script>
<s:layout>
<s:HorizontalLayout />
</s:layout>
<s:Label id="label" text="{buttonText}" />
<s:Button label="{label.text}" />
</s:Application>
上面的代码也许能够运行,然而,它也许不能运行。它假定 Label 的text 属性已经设置完毕,因为 button 组件的label. text 将与Label. text 属性绑定。如果你编译该应用程序,你也会收到一个编译时间告警信息(参见图6)。
图6. 在 Problems 视图显示的编译时间告警信息
下面是另一个范例。它假定第一个 TextInput 控件的值已经设置。这一类型的赋值也会导致编译器产生绑定所需的所有代码。你必须决定是否需要该代码或是否选择直接赋值 (y=35)。
<?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="1024" minHeight="768"> <s:TextInput id="textInput1" x="10" y="0" /> <s:TextInput id="textInput2" x="0" y="{textInput1.x+25}" /> </s:Application>
在许多情形下,你可以不使用数据绑定很方便地编写你的代码,而是使用事件事件进行赋值操作。你可以通过使用合适的组件生命周期事件或覆盖childrenCreated() 和 initializationComplete() 等组件设置一个值,以便进行赋值操作。此外,你可以 ChangeWatcher 侦听数据的更改,这一方法代价较小。当使用 ChangeWatcher 时,记住在许多情形下,你可以避免使用 ChangeWatcher ,因为你可以人工获得通知。例如,Flex 的所有收集对象具有一个能够广播的 collectionChange 事件,你可以使用该事件在收集对象中人工获得更改通知。
请查看下面范例:
<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="1024" minHeight="768"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public var dp:Array = [ { label:"New York", data: "New York" },
{ label:"Miami Beach", data: "Miami Beach" } ];
protected function creationCompleteHandler(event:FlexEvent):void
{
cb.dataProvider = dp;
}
]]>
</fx:Script>
<mx:ComboBox id="cb" editable="false" width="100" />
</s:Application>
该代码看起来是一个 Flex 应用程序的相当标准代码。然而,这里给出的绑定类型是不需要的。你可以使用事件处理程序的直接赋值方式取代绑定方式。
<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="1024" minHeight="768"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
public var dp:Array = [ { label:"New York", data: "New York" },
{ label:"Miami Beach", data: "Miami Beach" } ];
protected function creationCompleteHandler(event:FlexEvent):void
{
cb.dataProvider = dp;
}
]]>
</fx:Script>
<mx:ComboBox id="cb" editable="false" width="100" />
</s:Application>