作者:Mihai Corlan—Adobe Platform Evangelist
从上个世纪90年代末开始,我一直从事与Web相关的技术,而且我接触的第一个服务器端技术是PHP。后来,我转向ColdFusion 和Java 的开发工作,但我始终认为自己是一个PHP开发人员。当AJAX技术出现时,我开始与Prototype和 script.aculo.us等架构打交道,并且着手创建自己的架构。
2006年底,我开始体验进行Flex开发。这有点类似速成学习班,因为我需要在大约4-6个星期内为FDS((Flex Data Services, 现在称为LiveCycle Data Services)将要问世的版本创建一个演示应用程序。尽管当时我是一个Flex 和FDS的新手,但该项目进展顺利,而且我非常享受这次开发以及学习过程。
然而,在享受的同时,我感觉到Flex的不同之处。我的意思是当我在进行ColdFusion 或Java Web 的开发工作时,我并没有觉得其与PHP相比有不同之处。这仅仅是一个寻找正确的API以及适应特定语言的问题。后来,当我开始在DHTML之上进行AJAX开发时,我感觉也没有不同之处。你仍然使用相同的技巧、利用服务器端语言来创建大多数网站,以及在网站各处插入一些趣味画面(对于本案例来说,它们是一些AJAX widgets)。
当我使用Flex创建我的第一个Web项目时,我的天啊,这是一个巨大的转变。客户端和服务器之间的清晰分离(除了服务器侧的业务逻辑之外的客户端侧业务逻辑)、需要进行编译而不是翻译的客户端侧技术、以及客户端的两种语言等,所有这些均需要用一种不同于传统Web开发的思维方式进行思考。
这就是我写作本文的原因。我希望与你分享一些与PHP相关的Flex特定的技巧。同时,我还希望通过将Flex与PHP进行比较引入Flex概念,当然它们的比较必须是有意义的。因此本文的目标读者是:
· 希望学习更多关于Flex 和Action Script 3 而不只是通过简单定义能够提供的内容的PHP开发人员
· 已经进行Flex应用程序编码尝试并且希望更广更深地了解Flex的PHP开发人员
本文没有涉及的内容是什么?试图改变你或说服你让你相信Flex优于X或Y不是我的本意。我坚信项目具有各种各样的类型,并且利用不同的工具能够完成这些项目。
另外,本文没有为Flex 或ActionScript 3提供完整的文件资料。目前,市面上有几十本专著的数百页资料论述该主题。关于Flex的文章也有成千上万篇。而我的意图是在将Flex概念与PHP类似概念进行关联是有意义的情形下,针对最重要的议题为你提供足够的信息。为了使得本文更为实用,我对其结构进行适当的安排并且尽力避免对细节进行过多的赘述。在本文的结尾部分,我提供了Adobe AIR 的简介和一些附加参考资料,以便于你能够查阅与本主题相关的更多详细信息。
最后需要说明的是,对于本文给出的大部分范例,我选择使用Flex 3进行编程。作出这样的选择有如下几个原因:首先,在写作本文时,Flex 4仍然是beta版本。其次,由于Flex 4主要是Flex 3的演化版本,因此这里涉及的大部分应用程序能够适用于Flex4,只需进行少许更改即可。在一些范例中,我将指出这些不同之处。对于PHP范例,我选择使用PHP 5.3作为编程参考语言。前面已经给出说明,现在让我们来看看下面的本文目录,然后开始用功学习。
1. 什么是Flex?
2. 为什么你需要关注Flex
2. MXML语言简介
2. CSS 式样
3. 在运行时修改MXML代码
1. 隔离语句
2. 数据类型、变量和常量
3. 函数和匿名函数(闭包)
4. OOP:类和接口
5. 变量作用域
6. 数组
7. 命名空间
8. 与XML的配合
4. Flex 是异步的
5. Data 绑定、元数据标签和反射
1. Flex SDK
2. Flex Builder / Flash Builder
3. 调试Flex 应用程序
10. 下一步计划是什么 ?
11. 总结
最简单的回答是:Flex仅仅是创建Flash应用程序的另一种方法。Flash应用程序是在SWF文件中编译的,并且由Flash Player在浏览器中进行播放。为什么我们需要使用另一种方法创建Flash应用程序?传统的Flash应用程序是使用Flash制作工具创建的。如果你查看一下该工具,你会发现它主要适用于设计人员。其中包括一个舞台(stage),一条时间轴线(timeline)以及各种绘画工具等。
当你在开发应用程序并且追求开发效率时,你需要各种组件,你希望通过重用代码尽可能地提高开发效率,最后但并不是最不重要的一点是,你需要一个新型的IDE。
因此,一种修正的回答可能是:Flex是一种能够帮助开发人员快速创建富因特网应用程序(Rich Internet Application)的开源框架,这些应用程序能够在Flash Player中运行。在2006年的今天,随着Flex 2、Flash Player 9和 ActionScript 3的推出,该框架已经趋于定型。目前的版本是Flex 3,2010初,其下一个版本Flex 4将要面世。
在Flex之下,你将发现下列语言和工具:
· 两种语言:MXML和ActionScript 3。Flex提供两种语言以便创建Flex应用程序。在下面的章节中,我将进一步地讨论每种语言。
· 一个富组件库
· 各种编译器和调试器
· 用于编译和调试Flex应用程序的各种命令行工具
由于Flex是一种开源框架,因此我极力推荐你访问该计划的主页http://opensource.adobe.com/flex并且下载相关的SDK。你能够从组建库中查阅到所有组件的源代码,你能够查询相关的开放程序缺陷和功能库(http://bugs.adobe.com/flex),以及查看各种规范的wiki 页面。
Flex提供的部分效率改善应该归功于其海量组件库。该组件库包含了所有你能够想象的UI组件(例如,各种输入框(input box)、面板(panel)、视窗(window)、滑动条(slider)、数据网格(data grid)、组合框(combo box)、折叠显示(accordio)和Tab设置(tab set)等等)。另外,该组件库还包含各种布局容器和表单元素。在下面的图中,你能够看到Flex 3可以提供的各种UI组件的屏幕截图(点击可以放大)。
如果这些组件仍然不够使用,则你可以进入相应的源代码,扩展这些组件以创建你自己的组件或从零开始创建新的组件。
在深入探讨什么是Flex之前,让我们暂停一下,重温为什么你需要关注Flex的原因。
传统的HTML Web应用程序具有“请求-响应”架构。在浏览器发送一个请求之后,相应的服务器回送一个页面,这样的周期不断重复。HTML 和 CSS为呈现该信息提供了卓越的选择, 正如可提出证据加以证明的那样,这是目前最佳的选择之一。然而,随着时间的推移,这种架构不仅局限于静态呈现,而已经扩展至应用程序平台。利用脚本技术,我们尝试创建动态页面以及设计服务器使得其能够对特定请求给出响应。更进一步地,通过添加DHTML 和AJAX ,我们能够将新的气息带入由Web服务器支持的页面:用户能够与载入页面互动并且在无需刷新整个页面的情形下改变相关的视图。
随着这些技术的演化,各种复杂的应用程序不断出现。一些Web应用程序已经开始复制许多桌面应用程序的功能而且同时能够保持Web应用程序的便利性(只要有浏览器和因特网连接的地方就能够使用Web应用程序)。因此,各种在线版本的电子制表软件和文本编辑器不断涌现。
然而,从可用性的角度来看,在线应用程序的用户友好界面要比桌面应用程序差。同时,如需创建这些复杂的Web应用程序,你必须掌握许多技术(JavaScript、DHTML、CSS、AJAX 库以及服务器端等技术 )的各种技巧,并且你必须具有处理不同浏览器之间差异的经验以及了解他们是如何实现HTML/CSS/JS的。因此,2002年,Macromedia提出了术语RIA(Rich Internet Applications)来描述一种结合了Web应用程序的优势和桌面应用程序的益处的新型应用程序。能够实现这一新型应用程序的技术就是Flash Player。
通常,如果你希望创建应用程序(而不仅仅是一个Web站点或Web页面),你可以使用Flex来实现。一些应用程序几乎不能使用HTML/JavaScript来创建,而另外一些应用程序很难跨浏览器一致运行。Flash Player 能够提供最好的图形引擎,它已经安装于98% 的具有因特网连接的计算机,并且能够将声音和图像视为“一等公民”。它支持麦克风(microphone)和Web摄像(webcam)功能、支持流媒体和数据推送(streaming and data pushing)服务、以及提供卓越的字体排印(typography)功能,其支持的功能可以填满很长的清单。
请看看下面三个应用程序以便了解使用Flex能够出现什么样的奇迹:
· SumoPaint 是一个免费使用的图像编辑应用程序;
· Mindomo是一个思维导图应用程序;
· Times Reader是一个源自《纽约时报》(The New York Times)的应用程序。
随着时间的推移,其他技术已经进入RIA领域。除了使得如Gmail 或 Google Spreadsheets 等应用程序成为现实的AJAX 不断发展之外,今天,我们还能够看到源自Microsoft的Silverlight应用程序以及源自Sun的JavaFX应用程序。
让我们回到浏览器以及Web应用程序是如何传送的。当浏览器发出一个请求,相应的服务器将使用静态内容(HTML/CSS/JS 代码)和脚本(这些脚本可能查询数据库或调用其他脚本,但最终他们会输出HTML/CSS/JS)的组合来准备一个页面。该页面由浏览器载入并且显示出来。在此,一个关键元素是,通常该页面(或响应)具有显示标记(presentation markup )以及烘焙至相同消息的数据。
当应用程序的新状态需要呈现时,浏览器发出一个新的请求,之后相应的服务器将准备请求的页面。而客户端“仅仅”显示该数据。
Flex应用程序以不同的方式工作。服务器发送已编译过的Flex应用程序 (SWF 文件) ,该应用程序能够在浏览器中使用Flash Player插件运行。通常,该SWF文件只能支持客户端侧的业务逻辑。如果需要数据(例如来自数据库),则Flex应用程序能够发送请求以获得这些数据。服务器只发送数据(数据的格式可以为XML、JSON或AMF3),并且客户端能够知道如何显示该数据。我们这里讨论的是面向服务的架构:
Flex应用程序实际上是客户端–一种能够使用由服务器提供的数据服务的客户端。该应用程序能够在浏览器不刷新页面或不重新装载SWF文件的情形下变更状态。该应用程序是一种能够不仅仅显示数据的客户端。因此,通过利用Flex 和Flash Player能够创建几乎任何对象,这些对象对于在Web上部署各种游戏、应用程序以及widget具有重要意义,而这些游戏、应用程序以及widget能够与“古典”Web应用程序以及其他应用程序进行集成。
到此为止,已经谈论太多的枯燥理论,让我们看看一些程序代码吧!
MXML语言简介
MXML是一种陈述性的、基于XML的语言。在Flex应用程序中,你可以使用MXML语言快速地创建应用程序的结构/外观。在Flex中,你使用MXML能够创建的应用程序,也可以使用ActionScript 3来创建。然而,反向操作不能成立。
如果你能够使用ActionScript 3来创建可以使用MXML完成的应用程序,那么为什么MXML会首先出现?通常学习和理解利用XML语言描述的用户界面比利用命令式语言描述的用户界面要简单得多。这样利用XML语言编写的用户界面将会具有较少的代码。另外,为陈述性语言建立工具比为命令式语言也简单得多。下面是利用MXML实现的一个范例“Hello world!”。
1: <Label text="Hello World!" fontSize="14" color="red" x="100" y="50"/>
在这段代码中,我使用了一个名称为Label的Flex组件在屏幕上显示若干文本字符。我将文本的属性设置为我期望的文本格式。另外,我希望能够对外观及该Label在屏幕上的位置进行(少许)客户化处理。因此,我使用了属性fontSize、color、x 和 y。我相信你会同意这是非常易于理解和学习的范例。
现在,考察一下利用ActionScript 3实现的相同范例:
我使用了7行代码来实现前面我仅用包含一个标记和若干属性的MXML实现的范例!现在,可以设想一下在一个真正的应用程序中,你采用大量的控件,并且在不同的容器中进行分组。那么,维护利用MXML编写的代码要比维护使用几百行ActionScript 3编写的代码更为简单。
尽管你能够使用MXML描述你的应用程序,但你不能使用MXML实现你的应用程序的业务逻辑。而你可以利用ActionScript 3实现这一目的。
Flex应用程序能够运行于Flash Player,而Flash Player只能支持ActionScript 2 和ActionScript 3。这意味着你在应用程序中编写的任何MXML代码必须通过相应的MXML编译器转换成ActionScript 3代码。然后,该代码通过ActionScript编译器被转换成Flash Player支持的字节代码(bytecode)(SWF文件)。
因此,几乎每个MXML组件的后面均存在一个ActionScript 3类(实际上,有些MXML标记没有相应的ActionScript 类,例如Script 和 Model)。在下面的范例中,这是一个源自Label 类的一个代码片段( snippet ):
在任何Flex应用程序中,你应该至少具有一个MXML文件,这是主应用程序。例如,下面是“Hello World!” 应用程序的完整代码。
根节点必须总是Application,而且这是定义命名空间的位置。在本范例中,我仅仅提供一个用于MXML语言和Flex组件的命名空间:mx(上面的代码是使用Flex 3编写的。如果使用Flex 4,则代码具有微小的差异,其中声明了多个命名空间)。
如果你编写自定义组件,则必须为其添加一个命名空间。例如,在下面的代码中,我声明了第二个命名空间指向我所创建的所有组件(在本范例中,我使用了一个我自己创建的名称为MyCustomLabel 的自定义label 组件):
到目前为止,你也许想知道Flex应用程序是如何处理不同页面的。对于HTML Web站点,通常不同状态是在不同页面实现的。而Flex应用程序与桌面应用程序非常相似。这意味着你只需使用一个MXML文件,即可在该页面上显示应用程序的不同状态。Flex能够提供许多手段来实现这一目的,这些方法包括使用如折叠显示(Accordion)、Tab设置浏览器(Tabsets navigator)和牌布局管理器(Card layout)的Flex组件以及Flex模块等。
你已经看到MXML代码能够用于定义应用程序的外观。但你也能够利用它并且通过扩展现有Flex组件创建自定义组件。让我们来看一个范例。假设在你的应用程序中具有若干表单,这些表单具有两个按钮:Save 和Cancel。观察一下该MXML自定义应用程序的代码(该代码是在一个名称为FormButtons.mxml的文件中创建的。所有MXML文件必须使用mxml 扩展名)。
当你创建自定义应用程序时,你能够选择需要扩展的任何组件(但你不能对Application进行扩展)。我选择扩展HBox (Horizontal Box),这是一个能够在相同行显示所有children的容器。在该容器的内部,我添加了两个按钮,一个用于Save,另一个用于Cancel。我还为每个按钮设置了id 属性。你可以使用id 属性值作为引用代码其他部分的对象的一种方式。这与在ActionScript代码中声明一个变量的方式是相同的。
现在,让我们看看你如何在一个Flex应用程序中使用该自定义组件:
Below you can see how the application looks:
你也许会认为在MXML中你只能使用视觉Flex组件(即最终能够被显示的组件)。实际上,这是不确切的。你可以使用表示数据的MXML标签(用于存储数据的对象)或操作数据的组件(能够从服务器查询数据或向服务器发送数据的组件)。下面,你能够看到一个generic对象组件的范例,该组件具有一个名称为name的特性(property):
1: <mx:Object id="myObj" name="Mihai Corlan"/>
正如我前面所述的那样,与Flex相伴的所有(几乎所有)Flex组件均具有ActionScript类,该类能够实现视觉外观(如果有的话)以及相应的逻辑。当你选择使用ActionScript 而不是 MXML创建一个自定义组件(不论其是否是视觉组件)时,你必须记住存在以下限制:在不带自变量的情形下,该类的构造器(constructor)必须能够被调用(如果具有自变量,则这些自变量应该具有默认值)。
返回到自定义组件FormButtons (具有两个按钮的组件),你也许注意到一个问题:如果你希望在一个Save 和 Cancel 标签不起作用的地方使用该组件将会怎样?你应该创建另一个带有你期望的标签(例如Show 和 Hide)的自定义组件吗?当然,这是一个选择,但这个组件不能缩放或外观不太优雅!你所真正期望的是一个更为通用的组件,以及一种使用代码变更组件的方法。这是为什么迟早你不得不在MXML代码中添加ActionScript代码。
在下面的范例中,我在组件的MXML代码中添加了ActionScript代码以定义两个存储了按钮使用的标签的变量。注意,我使用了一个新的标签Script,并且在该标签之中使用了CDATA。这是因为在XML文档之中,像>、<和& 等字符是非法的(如果它们没有换码)。另外,现在我将不会把太多重点放在ActionScript代码上,但我将在后面的章节中更深入地讨论ActionScript代码。
我定义的变量可以在使用该组件的Flex应用程序中设置。下面,让我们来看看在使用新的自定义组件之后,变更的Flex应用程序代码的构成。
注意,FormButtons 标签具有两个属性: label1和 label2。这是为什么你能够在这些按钮上设置期望显示的文本。并且这是你使用的机制以便将更多的行为添加至MXML组件(使用ActionScript代码)。在真正的应用程序中,你可能希望将一个行为与每个按钮进行绑定,以便当按下按钮时,就会产生相应的结果。你可以使用ActionScript代码编写通过按下按钮即可触发的各种函数。
另外,还有一种在MXML至添加ActionScript 代码的方法。你可以先创建一个ActionScript 文件(在本范例中,该文件的名称为buttons.as),然后将该文件包含于MXML文件中。你可以通过添加一个具有source 属性的 Script 标签实现这一操作 ,而该属性指向该ActionScript文件。下面是这一方法的代码。
现在,让我们后退一小步,然后推测一下当MXML编译器解析FormButtons.mxml 文件时会发生什么情况。你已经知道所有代码将会转换成ActionScript代码。但对于我添加的现有ActionScript代码(两个变量)会发生什么情况呢?MXML编译器将会把每个MXML文件编译至一个ActionScript 类。在这种情形下,我将获得一个名称为FormButtons(因为这是该文件的名称并且它可以用于该类的名称)的类,该类扩展了HBox 组件(因为我选择了 HBox 作为该组件的根节点)。该类中的所有ActionScript代码将会变成该类的成员:变量(例如本范例中的变量)将会变成实例变量,并且函数将会变成实例方法。
CSS式样
到目前为止,你也许想知道你是否能够改变视觉Flex组件的外观。Flex组件具有类似HTML CSS的技术?答案是肯定的,Flex 支持 CSS。在Flex 4中,对CSS的支持已经扩展至允许不仅可以基于类的名称而且可以基于ID进行式样定义,以支持伪选择符(pseudo-selector)(例如,对于一个按钮来说,你应该具有下选择符(down selector)、上选择符(over selector)等等)以及其他更多功能。
与在HTML中一样,式样可以在行中(在MXML代码内部)定义或在一个独立的文件中定义。让我们先回到自定义组件FormButtons, 然后设置若干式样。如果你选择在一个独立的文件中定义试样,则必须使用一个Style 标签并且将路径设置为 source 属性中的式样文件。
我创建了一个名称为Button1 的CSS类,该 CSS类定义了标签颜色以及字体大小。然后,我使用第一个按钮的styleName 属性将式样设置为第一个按钮。至此,该应用程序如下图所示:
CSS式样在运行时能够改变(在Flex应用程序载入浏览器之后),并且该应用程序的外观也会立即随着改变。
在Flex 4中,Adobe添加了名称为MXML用于图形的新语言,该语言添加了原语(primitive)、效果(effect)、面具( mask) 和2D 转换功能。你可以使用这些新的标签在MXML文件中创建皮肤(skin)类,然后你能够将该类设置为你期望对其进行皮肤粘贴的组件。在下图中,你能够看到一串以Flex 4为皮肤的图像。左边给出了该串图像的默认状态,而右边给出了该串图像的打开状态。你可以点击这里 观看处于运行状态的应用程序。
当你在关于Flex应用程序外观的自定义的文档中徘徊时,你也许能够理解术语“皮肤粘贴”的含义。你可以进行图形皮肤粘贴(graphical skinning )或编程皮肤粘贴(programmatic skinning )以便改变相应的外观。点击这里 可以获得关于这方面问题的佳文。
有时候你希望在运行时变更UI组件。也许你希望根据你从服务器中检索到的数据来实时地建立一个表单。同样,你也能使用ActionScript代码实现这一任务。任何视觉Flex组件均具有添加一个新子类、移除一个新子类以及获取所有子类等方法。如果你愿意,你可以将这些方法与在HTML中使用JavaScript改变DOM的方式进行比较。然而,它们之间存在差异:利用JavaScript你可以注入你从服务器检动态索到的HTML代码(通过一个AJAX 调用)。但在Flex中,这是不可能,并且在Flex中不存在eval() 函数。然而,在主应用程序载入之后,有方法可以载入其它Flex应用程序或Flex模块。
当你了解一个组件的所有不同视图时,你能够使用MXML States 来实现相同组件或应用程序的不同状态。状态功能是Flex 4对比Flex 3的实现方式改善非常显著的地方,这使得这些状态更加易于使用并且添加更多功能。在Flex 4,状态的工作方式如下:
1. 你可以定义若干状态并且指定默认状态
2. 你能够指定在一个特定的组件应该出现在哪些状态中
3. 你可以指定在状态出现的位置每个状态的任何属性的独立值
假设你希望创建一个处理应用程序登录功能的组件。你希望使用该组件显示登录表格,并且在登录成功之后,你希望显示退出按钮以及用户姓名。
下面是使用Flex 4创建的登录/退出组件:
上面的代码应该是很容易理解的。作为顶部容器,我使用一个具有设置为HorizontalLayout 布局的Group组件(这与用于上面范例Flex 3中的Hbox具有相同的效果)。我已经在该文件的顶部为该组件定义了可用状态。接下来,我还定义了按钮、文本输入和标签。注意一下指定该组件在什么状态下会出现的includeIn 属性。另外,文件中还包含一个excludeFrom 属性。如果你希望在所有状态下定义一个按钮,则无需为这两个属性指定任何状态。最后,你可以看到我为这两个按钮的点击属性指定了一个表达式。例如,表达式click=”{currentState=’logged’}” 告诉Flex 当按钮被点击时,应该将该组件的状态改变为名称为logged的状态。
尽管我一直在讨论MXML语言,但我已经将越来越多的ActionScript代码加入了这些范例。这是一个迹象:该到讨论第二种Flex语言ActionScript 3的时候了。
【国内下载】Flex 3 Builder :http://g.csdn.net/5120749
【国内下载】Adobe Flash Builder 4 :http://g.csdn.net/5105812
【官方下载】Flex 3 Builder :http://g.csdn.net/5121278
【官方下载】Adobe Flash Builder 4 :http://g.csdn.net/5120750
未完待续-----