您的位置:首页 > 其它

自定义真正可重用的Flex组件

2010-12-16 11:14 375 查看
来源: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>


注意 dataField 和 labelFunction 属性如何通知组件从Kanagroos读取数据,而且对它没有依赖。这两种方法可以使组件重用。即使开发人员不能对Kangaroo 类做修改,比如它在第三方类库,但是他们仍然很容易在DataGrid 中渲染这些对象。

数据接口反模式

一个普遍的错误是把组件渲染的数据,去实现指定接口。例如:一个分布栏组件渲染简单图片,如下图:



分布栏显示不同大小的地区,每个都有个标示,通过使用IRegion 对象数组进行设计。

public interface IRegion{
  function get label() : String;
  function get size() : int;
}


这个分类栏会通过IRegion接口提取size 和 label 信息来渲染每个区域。理论上这个接口让组件和实际对象解耦了,任何实现该接口的类都可以被渲染。实际上这是设计上的错误。使用Iregion 接口令重用性有了限制。使用这个组件前,一定需要把这个接口加载进原有的数据类里。 更坏的情况是,这些数据类可能在另外的类库,或是在另一开发小组。因而不得不把这个接口加载进来。导致组件并不是真正的可重用。

可重用的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
}


这种方法和 dataField 差不多,但使用更灵活了。因为在组件渲染之前,可以通过函数来计算或格式化返回值。

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
}


这个方法非常强大,不过一般只用在复杂的组件。如 Tree。开发者如果要在Tree渲染一个新的类,他们要自行实现ITreeDataDescriptor 接口。

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。要注意的是反对使用自定义的接口来限制你的组件重用性。

附言
可重用组件习惯使用动态属性,这里做了些权衡取舍。因为访问动态属性比强类型属性慢。而且没有编译期的类型检测。然而它的好处是使用更灵活,更少依赖。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: