自定义真正可重用的Flex组件
来源:http://blogs.adobe.com/tomsugden/2009/12/writing_genuinely_reusable_fle.html
在大型企业项目里,经常要为Flex 类库写一系列可重用的组件。理论上来说,相同的组件总可以被Flex 或 AIR客户端的modules 和 sub-applications 复用,带来高度一致性和快速开发的好处。然而在实际中,有一些错误用法限制了组件的重用性。本文阐述了是什么使得组件真正可重用,并强调了一些在Flex SDK 里使用的技术,以此来编写出更具重用性的自定义组件。
什么方法令组件可以真正重用?
组件重用性存在不同等级。一个真正可以重用的组件应该可以接受任何类型的数据进行渲染。完全可以适应数组、动态Object或者是Kangaros(具体对象)的集合。Flex DataGrid 组件有这样一个属性。
<mx:DataGrid dataProvider="{ kangaroos }">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Weight" labelFunction="calculateWeight"/>
</mx:columns>
</mx:DataGrid>
数据接口反模式
一个普遍的错误是把组件渲染的数据,去实现指定接口。例如:一个分布栏组件渲染简单图片,如下图:
分布栏显示不同大小的地区,每个都有个标示,通过使用IRegion 对象数组进行设计。
public interface IRegion{
function get label() : String;
function get size() : int;
}
可重用的Flex SDK组件
Flex SDK 提供很多可重用的组件,它们的实现有以下一些标准方法:
1.Data Fields
2.Data Functions
3.Data Descriptions、
4.Factory Objects
现在就说明下这些方法。使用这些技术可以令到自定义的组件具有真正的重用性。
Data Fields
Data field 是一个字符型属性。代表另外属性名称。例如:ComboBox 的 labelField 或者DataGridColumn 的dataField 、dataTipField 属性。
<mx:ComboBox dataProvider="{ items }" labelField="name"/>
组件的实现是使用 dataField 去读取 items 属性值。如:
for each (var item:Object in dataProvider){
var value:Object = item[dataField];
// do something with the value
}
这是个很简单的方法,但提供很大灵活性。这组件可以读取任何对象的任何属性。
Data Functions
Data Function 是个函数类型。代表另外函数的引用。如:ComboBox 的 labelFunction 或DataGridColumn 的 dataFunction 属性。
<mx:DataGridColumn headerText="weight" dataFunction="calculateWeight"/>
这组件然后调用dataFunction,一般用data 的item 作为参数。如:
for each (var item:Object in dataProvider){
var value:Object = dataFunction(item);
// do something with the value
}
Data Descriptions
Data description 是一个接口,组件可以使用它来分析渲染数据。开发者可以使用自己实现的接口来处理组件的渲染数据。在Tree 组件可以看到
<mx:Tree dataProvider="{ items }">
<mx:dataDescriptor>
<my:MyDataDescriptor/>
</mx:dataDescriptor>
</mx:Tree>
Tree 可以使用dataDescription 接口分析数据特性。如:
for each (var item:Object in dataProvider){
var isBranch:Boolean = dataDescriptor.isBranch(item, dataProvider);
// do something with the outcome
}
Factory Objects
Factory Object 是一个 IFactory 属性,用于动态生成实例。如:List 和DataGrid 的 itemRenderer 和 ComboBox 的dropdownFactory 属性。
<mx:List dataProvider="{ items }" itemRenderer="my.package.MyItemRenderer"/>
这个组件使用Flex SDK 的标准IFactory 接口来创建实例。
var itemRenderer:Object = itemRenderer.newInstance();
然后把data items 给IDataRenderer 接口创建的实例赋值
if (itemRenderer is IDataRenderer){
IDataRenderer(itemRenderer).data = item;
}
这种方法提供操作部分组件的视图外观。通过提供自定义的itemRenderer,可以达到完全不同的结果。处理数据的逻辑的复杂程度可以根据需求来决定。而且还可以封装在ItemRenderer 类里面。前面提到,组件使用工厂(Factories)时候,应该定义有意义的默认值。所以组件可以直接使用,不需要设置特别的Factories。所有 的ListBase组件都提供了默认值。如DataGrid 默认是DataGridItemRenderer。
这里值得注意是Flex 编译器和IFactory 有特别关系。当这个属性在MXML 设置了,会自动转换成类名字,然后把ClassFactory 的实例嵌入到组件里。这样使得组件更容易使用,开发者不用手动去实例对象。只需指定类名或定义一个嵌入组件。
总结
当需要重用组件时,要记住这简单的规则:一个可重用的组件应该可以渲染任何类型的数据。最好的实现方法是遵守Flex SDK的约定:data fields, data functions, data descriptors 和 object factories。要注意的是反对使用自定义的接口来限制你的组件重用性。
附言
可重用组件习惯使用动态属性,这里做了些权衡取舍。因为访问动态属性比强类型属性慢。而且没有编译期的类型检测。然而它的好处是使用更灵活,更少依赖。