創建一個簡單的自定義組件
我們可以在一個MXML文件中創建一個MXML組件,這個文件的名字就變成了這個自定義組件的標籤名。比如:一個文件名字叫做CountryComboBox.mxml,使用標籤<CountryComboBox>就可以定義這個組件。
一個MXML組件的根標籤,是一個組件的標籤,可以是Flex組件也可以是其他MXML組件。根標籤指定http://www.adobe.com/2006/mxml作爲命名空間。例如,下邊的MXML組件擴展標準的Flex ComboBox控件。可以把自定義組件的文件放在項目的根目錄中,也可以放在一個子目錄中。Adobe推薦後一種方法作爲最佳實踐。在這個例子中自定義組件被放置到componects文件夾中。在主程序的MXML文件中,映射componects文件夾到custom命名空間,使用全標籤名<custom:CountryComboBox>來應用這個組件。
提示:在現實世界中,你可能看到自定義組件被放置在公司域名倒敘的目錄結構中。(比如, xmlns:custom="com.adobe.quickstarts.customcomponents.*")。這個習慣可以避免不同製造商在命名組件名稱相同時導致的衝突。例如,兩個組件庫可能各自包含Map組件,如果一個com.vendorA.*一個在com.vendorB.*那麼他們就不會衝突
例子
components/CountryComboBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:dataProvider>
<mx:String>United States</mx:String>
<mx:String>United Kingdom</mx:String>
<!-- Add all other countries. -->
</mx:dataProvider>
</mx:ComboBox>
主文件
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:custom="components.*"
width="220" height="115"
>
<custom:CountryComboBox/>
</mx:Application>
引用一個自定義組件的屬性和方法
CountryComboBox.mxml指定ComboBox作爲其根標記,那麼你可以引用所有ComboBox的屬性和方法,在自定義組件的MXML標記中,或者在<mx:Script>標記中的ActionScript中也可以。例如,下邊的例子爲自定義組件指定了rowCount屬性和一個關閉事件的監聽器。
提示:在Flex中,MXML文件在編譯成SWF文件之前,先編譯成ActionScript類文件。當你爲自定義的MXML組件指定根標記後,你實際上使你的自定義組件類擴展了根標記的組件類。這就是爲什麼自定義組件繼承了根標記組件的方法和屬性。
在下邊的例子中,CountryComboBox MXML文件編譯爲一個class文件。Flex的命名習俗是組件名首字母大些,也對應類名。
例子
components/CountryComboBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:dataProvider>
<mx:String>United States</mx:String>
<mx:String>United Kingdom</mx:String>
<!-- Add all other countries. -->
</mx:dataProvider>
</mx:ComboBox>
主應用程序的MXML文件
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:custom="components.*"
width="270" height="170"
>
<mx:Script>
<![CDATA[
import flash.events.Event;
private function handleCloseEvent(eventObj:Event):void
{
status.text = "You selected: /r" + countries.selectedItem as String;
}
]]>
</mx:Script>
<mx:Panel
title="Custom component inheritance"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10"
>
<custom:CountryComboBox
id="countries" rowCount="5"
close="handleCloseEvent(event);"
/>
<mx:Text id="status" text="Please select a country from the list." width="136"/>
</mx:Panel>
</mx:Application>
創建一個複合的自定義組件
複合自定義組件中包含多個組件定義。爲了創建複合自定義組件,應該指定一個容器,作爲根組件,然後添加Flex組件作爲其子組件。
下邊例子中的AddressForm組件通過將Form容器作爲根組件創建了一個地址表單。然後定義了幾個Form容器的子組件。這些子組件中包含其他自定義組件—CountryComboBox。
例子
components/AddressForm.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Form
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:custom="components.*"
>
<mx:FormItem label="Name">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Street">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="City">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="State/County">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Country">
<custom:CountryComboBox/>
</mx:FormItem>
</mx:Form>
components/CountryComboBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:dataProvider>
<mx:String>United States</mx:String>
<mx:String>United Kingdom</mx:String>
<!-- Add all other countries... -->
</mx:dataProvider>
</mx:ComboBox>
Main application MXML file
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:custom="components.*"
viewSourceURL="src/MxmlComponentComposite/index.html"
width="400" height="290">
<mx:Panel
title="Composite component"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10" >
<custom:AddressForm />
</mx:Panel>
</mx:Application>
如果自定義組件文件中的根標記包含子組件時,當你在其他MXML文件中引用這個自定義組件標籤時,這個標籤不能包含子標籤。如果你在MXML文件中定義了一個空容器,當你使用這個組件標籤時,這個標籤就可以包含子標籤。
例如,下邊的AddressForm的用法是不正確的,不能被編譯。
<!-- Incorrect -->
<custom:AddressForm>
<mx:FormItem label="Post code">
<mx:TextInput/>
</mx:FormItem>
</custom:AddressForm>
如果你必須擴展複合標籤的功能,可以創建一個以符合組件作爲根標記的自定義組件。
注意:這個關於子組件的限制只是在子組件是可視組件的時候起作用。可是組件都是UIComponent組件的子類。你永遠都可以向不可視組件中插入標記,比如,ActionScript塊,style,effect,fomatters,validator,和其他類型的不可視組件。不管你如何定義的自定義組件。
創建可重用的MXML組件
創建自定義組件的一個公共目標是創建可配置的、可重用的組件。例如,你想要創建一個自定義組件,帶有屬性、分發事件、定義新的樣式屬性、有自定義皮膚,或者其他自定義功能。創建自定義組件的一個預期回報是可重用。也就是說,你希望自定義組件緊緊的關聯在你的程序中那?還是可以用在多個程序中?
爲特定應用程序所編寫的緊耦合的組件,經常使它依賴應用程序的結構,變量名,或其他細節。如果你改變應用程序,你可能需要修改緊耦合的組件來反應這種變化。緊耦合的組件如果不重寫很難應用到其他應用程序中。
設計一個鬆耦合的組件來重用,它需要定義明確的接口來指定如何給組件傳遞信息,和組件如何嚮應用程序傳回結構。
典型的,通過定義鬆耦合組件的屬性,來向它傳送信息。屬性是通過定義固有的存取器(setter和getter方法)和指定參數的數據類型來實現的。在下邊的例子中,CountryComboBox自定義組件定義了useShortName公共屬性。這個屬性通過get useShortName和set useShortName存取器方法使_useShortName變量暴露。
_useShortNames私有屬性前的Inspectable元數據標籤,定義了一個屬性,這個屬性出現在Adobe Flex Builder中的屬性提示,和標籤內省中。也可以使用這個元數據標籤來限制對屬性值的訪問。
提示:所有公共屬性會暴露在MXML的代碼提示和屬性檢查器中。如果你有關於這個屬性的額外的信息,能夠幫助代碼提示或屬性檢查器(比如枚舉值,或隻字符串是一個路徑),那麼也把這些而外信息添加到[Inspectable]元數據中。
MXML代碼提示和屬性檢查器的數據來源是一樣的。所以這兩個的顯示應該是一樣的。
另一方面,ActionScript的代碼提示是不需要元數據的,所以根據坐在的範圍,你一直可以看到適當的代碼提示。
Flex Builder 使用標識符(比如public private protected static)加上正確的上下文從而決定ActionScope的代碼提示。
定義返回信息到主程序的組件的最佳實踐是設計組件爲發送包含返回值的事件。那樣,主程序就能夠定義事件處理器,來處理時間並進行適當的動作。也可以在數據綁定中使用事件。下邊的例子中,使用Bindable元數據標籤,使userShortName作爲一個綁定的屬性。useShortNames屬性的seter方法發送改變事件,通過Flex Framework來實現數據綁定起作用。
例子
components/CountryComboBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ComboBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
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 2
[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;
}
]]>
</mx:Script>
</mx:ComboBox>
應用程序MXML文件
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:custom="components.*"
viewSourceURL="src/MxmlComponentAdvanced/index.html"
width="260" height="200"
>
<mx:Panel
title="Advanced custom components"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10"
>
<!-- Set a custom property on a custom component -->
<custom: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:ControlBar>
</mx:Panel>
</mx:Application>