25.Defining data models定义数据模型
初次翻译,错误之处必然不少,敬请见谅。
翻译日期:2008-03-01
译者:ShiLiangShuai(http://hi.baidu.com/shiliangshuai)
Flex版本:3
原文地址:
所处章节:Flex Developer Center -> Flex Quick Starts ->Deploying components
要看程序运行效果请查看原文,或自己手工编译程序。
一个数据模型就是一个ActionScript对象,这个对象的属性用来存储应用程序之地你的数据。在向服务器发送数据之前,或者从服务器接收数据但还没有使用之前,数据模型提供一个在Flex应用程序中存储数据的途径。Adobe Flex应用程序与服务器之间的通信只发生在Flex应用程序需要检索的数据尚未可用,和使用Flex应用程序中的新数据更新服务器端 的数据源。
你使用模型不是一定需要连接到服务器。例如,你可以使用MXML或ActionScript静态对象,或者从本地XML文件中获取。
在MXML标记、ActionScript函数、或者ActionScript类中,都可以定义数据模型。将模型写在MXML中有利于快速开发和简化数据存储,但是不能提供额外的功能,你也不能设置模式属性的数据类型。如果你想设置数据类型或者为而外的功能提供函数,就要使用基于ActionScript类的数据模型。一般而言,基于MXML的数据结构用于简单的数据结构,ActionScript用于复杂的数据结构,并且客户端有很多商业逻辑。在Model-View-Controller设计模式中,数据模型对应Model部分。
注意:Model-View-Controller(MVC)设计模式提供一个通用的解决方案对于在应用程序中的紧耦合,通过分离业务逻辑和显示逻辑,封装一个单独的位置为紧耦合。应用程序中的数据来自Model,显示层是View,控制器是二者时间的媒介并且包含业务逻辑。关于MVC和其他设计模式的更好的说明,请参看O’Rerlly的《Head First Design Pattens》
当你规划一个应用程序,你需要决定应用程序需要存储的数据的类型。这帮助你决定了数据模型的类型。例如,加入你决定你的应用程序必须存储关于雇员的数据。一个简单的雇员模型可能包含名字、部门、E-Mail地址属性。
在Flex中你能够通过多种途径定义数据模式:
使用<mx:Model>标记
使用基于脚本的模型
使用基于类的模型
使用<mx:XML>标记
使用<mx:Model>标记
基于MXML标记的定义最通用的方式是使用<mx:Model>标记,这个标记编译为ActionScript对象,当你的数据具有层次关系的时候编译为一系列树状对象,编译后的对象是没有类型信息的。对象树的叶子是可量化的值。因为模型定义在<mx:Model>标记时不包含类型信息或业务逻辑,他们只试用于简单的需求。当你需要定义属性类型或者想添加业务逻辑,那么在ActionScript中定义数据定义模型。
你既可以在MXML文件中的<mx:Model>中定义数据,或者使用标记source属性从额外的数据文件的加载数据。当使用source属性时,额外的数据文件被编译进SWF文件中。他并不是在运行时加载的。
嵌入在标记或者在原文中数据模型声明,必须由于单独的root节点包含所有的节点。你能够使用MXML绑定表达式:例如在模型中声明{employeeEmail.text}。这个方式你可以绑定form字段的内容到一个结构化的数据描述。
在下边等例子中,定义一个数据模型来保存雇员数据细节。这个数据模型使用数据绑定来接收数据界面中各种form控件的数据。例如,无论输入怎么变化,email 数据节点从emloyeeEmail TextInput控件的text属性获得数据。类似的,modelEmployee数据模型中的name.first和name.last属性使用数据绑定从employeeName文本域中获得值。
建议:你能够使用两个test字段简化例子,一个是员工的first name一个是员工的last name。如果你使用这种方式创建这个例子,那么亦可以绑定employee.name.first属性到employeeFistName.txet属性,并且employee.name.last属性到employeeLastName.txet属性。这样就简化了代码,因为你不需要处理字符串:将单一的employeeName文本域拆分为first name和last name。然而,你必须决定一个更重要的问题:是你的工作更简单,还是使用户使用你的应用程序时更简单。
在这个例子中,在一个单一的文本框中输入全名,对于用户来说是更简单的。拆分employee的名字到两个文本域使你的工作更简单,但用户使用起来更复杂了。当开发你的应用程序时,保持这思想。(在现实时间的应用程序中,你应该使用更高超的技术,因为middle name和输入名字时需要执行的校验。
Example
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
horizontalAlign="center" verticalAlign="middle"
width="360" height="240"
>
<!-- This model holds information on a single employee -->
<mx:Model id="modelEmployee">
<employee>
<name>
<first>{employeeName.text.substring(0, employeeName.text.indexOf(" "))}</first>
<last>{employeeName.text.substring(employeeName.text.indexOf(" ")+1)}</last>
</name>
<department>{employeeDepartment.selectedItem}</department>
<email>{employeeEmail.text}</email>
</employee>
</mx:Model>
<!-- Script to process the addition of a new employee -->
<mx:Script>
<![CDATA[
import mx.controls.Alert;
private function addEmployee(event:MouseEvent):void
{
var message:String = "Name: ";
message += modelEmployee.name.first + " " + modelEmployee.name.last + "\r";
message += "Department: " + modelEmployee.department + "\r";
message += "Email: " + modelEmployee.email;
Alert.show(message, "New employee added!");
}
]]>
</mx:Script>
<!-- User Interface -->
<mx:Panel title="New employee details">
<mx:Form>
<mx:FormItem label="Name:">
<mx:TextInput id="employeeName"/>
</mx:FormItem>
<mx:FormItem label="Department:" width="100%">
<mx:ComboBox id="employeeDepartment">
<mx:dataProvider>
<mx:String>Administration</mx:String>
<mx:String>CEO's Office</mx:String>
<mx:String>Development</mx:String>
<mx:String>Finance</mx:String>
<mx:String>IT</mx:String>
<mx:String>Support</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
<mx:FormItem label="Email:">
<mx:TextInput id="employeeEmail"/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar horizontalAlign="center">
<mx:Button label="Add employee" click="addEmployee(event);"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
使用基于脚本的模型
作为可替代基于MXML模型的方式,可以在<mx:Script>标记中定义数据模式。下边的例子与前一个实现的功能相同,不过是把模式定义在ActionScript脚本块中。
提示:如果你想更简单的通过大括号语法使用数据绑定,那么在MXML中定义你的数据。
在下边的例子中,在ActionScript中定义一个层次结构对象的数据模型。在initailize事件处理器中,增加updateModel方法作为view视图中的form元素的change事件处理器。updateModel()方法类似于View Helper。他检查你视图中控件的值并且使用你输入到控件中的值更新数据模型。你也可以定义validateModel()方法,他在数据模型上执行非常简单的校验并且设置一个modeValid标志。绑定Add employee按钮到modelValid标志,这样,用户只有模型符合逻辑时才能被提交。
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
viewSourceURL="src/DataModelsModelAS/index.html"
horizontalAlign="center" verticalAlign="middle"
width="360" height="240"
initialize="initializeHandler(event);"
>
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
import mx.controls.Alert;
// Boolean to keep track of valid the model is valid
[Bindable]
public var modelValid:Boolean = false;
// Model
private var modelEmployee:Object =
{
name:
{
first:"",
last:""
},
department:"",
email:""
}
// Set up listeners for form item change events
// when the application starts.
private function initializeHandler(event:FlexEvent):void
{
employeeName.addEventListener(Event.CHANGE, updateModel);
employeeDepartment.addEventListener(Event.CHANGE, updateModel);
employeeEmail.addEventListener(Event.CHANGE, updateModel);
}
// Gets called when a form item on the view changes.
// Acts like a View Helper: It inspects the view to
// update the model with data supplied by the user.
private function updateModel(event:Event):void
{
// Split the employee's full name string into
// first name and last name strings.
var employeeFullName:String = employeeName.text;
var nameSpaceIndex:uint = employeeFullName.indexOf(" ");
var employeeFirstName:String = employeeFullName.substring(0, nameSpaceIndex);
var employeeLastName:String = employeeFullName.substring(nameSpaceIndex+1);
// Store data values from the view in the model.
modelEmployee.name.first = employeeFirstName;
modelEmployee.name.last = employeeLastName;
modelEmployee.department = employeeDepartment.selectedItem;
modelEmployee.email = employeeEmail.text;
// Do some simple validation on the model.
validateModel();
}
// A very simple custom validation method.
private function validateModel():void
{
modelValid =
modelEmployee.name.first != "" &&
modelEmployee.name.last != "" &&
modelEmployee.department != "" &&
modelEmployee.email != "";
}
// The handler for the Add employee button
private function addEmployee(event:MouseEvent):void
{
// Display the data values in the model
var message:String = "Name: ";
message += modelEmployee.name.first + " " + modelEmployee.name.last + "\r";
message += "Department: " + modelEmployee.department + "\r";
message += "Email: " + modelEmployee.email;
Alert.show(message, "New employee added!");
}
]]>
</mx:Script>
<mx:Panel title="New employee details">
<mx:Form>
<mx:FormItem label="Name:">
<mx:TextInput id="employeeName"/>
</mx:FormItem>
<mx:FormItem label="Department:" width="100%">
<mx:ComboBox id="employeeDepartment">
<mx:dataProvider>
<mx:String>Administration</mx:String>
<mx:String>CEO's Office</mx:String>
<mx:String>Development</mx:String>
<mx:String>Finance</mx:String>
<mx:String>IT</mx:String>
<mx:String>Support</mx:String>
</mx:dataProvider>
</mx:ComboBox>
</mx:FormItem>
<mx:FormItem label="Email:">
<mx:TextInput id="employeeEmail"/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar horizontalAlign="center">
<mx:Button
label="Add employee"
enabled="{modelValid}"
click="addEmployee(event);"
/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>