Ajaxify您的Flex应用程序

嵌入网页容器中的Flash应用程序通常是独立运行的,网页只不过是哑容器。 本文将演示如何利用ActionScript外部接口在两者之间进行双向通信。 请密切注意,以便您可以在最后完成测验并参与竞猜,以获取Adobe CS4 Web Premium和Flex Builder 3 Pro的免费副本。

富互联网应用程序一词仍然是Web开发当前的流行语之一。 各种各样的供应商投入了热情,并提供了自己的RIA开发风格。 令我们感到惊讶的是Adobe的Flash平台是其中最有趣的平台之一。 Flash Platform的核心元素显然是其虚拟机,也称为Flash Player。 利用运行时的最常见的开发技术是Adobe的Flash创作环境,Flex Builder和开源Flex SDK,后者均包含Flex框架。

Flash和Flex是非常酷的技术-尤其是当您在浏览器范围之外浏览并考虑在用户桌面上的AIR中运行基于Flash的RIA时。 但是,Flash平台只是当今人们在Web奇妙世界中使用的一种技术,因此,在本教程中,我们将研究在Flash Player中运行的基于Flex的应用程序可以采用的几种不同方式。与外界沟通。

技术要求

我们这里讨论的许多内容对于Flash和Flex都是有效的,因为我们实际上是在谈论Flash Player的功能和API。 本教程中的所有示例均使用Flex 3,因此您可能要开始运行开源Flex 3 SDK或Flex Builder 3。

从这里开始,我将使用术语“ Flex应用程序”作为使用Flash或Flex创建的基于.swf文件的应用程序的同义词。 使用Flash Authoring环境将此处提供的信息转移到其中应该相当简单。 如果您想进一步探索,则可以从使用Flash CS3或CS4中受益。 从Flash Player的角度来看,示例代码在Flash Player版本9和10中应该可以正常工作。

通常,基于.swf的应用程序与Flash Player结合使用是在称为“容器应用程序”的环境中执行的。 首先,让我们仔细研究一下Flex应用程序最常见的环境:网页容器(有时称为“ HTML包装器”)。 除了使用常见的网页容器环境外,Flash Player还提供了其他一些部署选项;例如, 我将提供一些参考,以在本教程结束时进行后续介绍。

HTML包装器

大多数读者可能会熟悉网页的结构以及在这样的环境中嵌入Flex应用程序的一般概念。 但是,当您开始尝试确保Flex应用程序在每种浏览器中都可以正常工作时,如果需要触发用户的Flash Player的自动更新,则可能会变得有些棘手。 使用Flash CS 3和4,Flex 2和3创建的应用程序必须在至少版本9的Flash Player中执行。(因此,您的应用程序可以使用新的虚拟机并正确支持ActionScript 3,例如以及其他一些很棒的东西)。

最简单的开始方法是使用已建立的模板,该模板已经具有代码,可以将Flex应用程序正确地嵌入到您的网页中。 Flex Builder 3项目带有HTML模板,提供了一个很好的起点。 下图显示了此类项目的文件夹结构。 文件夹html-template包含模板文件,这些文件是在Flex应用程序编译时针对HTML环境的项目设置进行自定义和填充的。 生成的编译文件位于bin-debug文件夹中。 重要的是要了解,重新编译项目时, bin-debug中对文件所做的任何更改都将被覆盖。 因此,应仅对html-template文件夹中的文件进行更改。

Flex Builder项目文件夹结构

记住这一点,我想解释一下HTML包装器的最重要部分。 基本上,HTML包装器页面使用JavaScript库(在页面顶部导入的AC_OETags.js )来确定浏览器客户端上实际可用的Flash Player版本。 然后,根据结果,将执行Flex应用程序或启动Flash Player的智能升级。 但是,如果尚未安装Flash Player或可用的Flash Player版本低于6.0.65,则JavaScript库将显示替代的HTML内容。 在HTML页面的更下方,您还可以找到带有<object><embed>标记的<noscript>部分。 如果JavaScript不可用或在客户端上禁用,则将执行此操作。

让我们仔细看一下对AC_FL_RunContent函数的调用以及出现在更下方的<object>标记:

AC_FL_RunContent( 
 "src", "FlexAndJS",
 "width", "100%",
 "height", "100%",
 "align", "middle",
 "id", "FlexAndJS",
 "quality", "high",
 "bgcolor", "#869ca7",
 "name", "FlexAndJS",
 "allowScriptAccess","sameDomain",
 "type", "application/x-shockwave-flash",
 "pluginspage", "http://www.adobe.com/go/getflashplayer"
);
...
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
   id="FlexAndJS" width="100%" height="100%"
   codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
 <param name="movie" value="FlexAndJS.swf" />
 <param name="quality" value="high" />
 <param name="bgcolor" value="#869ca7" />
 <param name="allowScriptAccess" value="sameDomain" />
 <embed src="FlexAndJS.swf" quality="high" bgcolor="#869ca7"
     width="100%" height="100%" name="FlexAndJS" align="middle"
     play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
     type="application/x-shockwave-flash"
     pluginspage="http://www.adobe.com/go/getflashplayer">
 </embed>
</object>
使用FlashVars数据传递到Flex应用程序

让我们回到本教程的原始主题。 我们想让我们的Flex应用程序与HTML包装器通信。 最简单的方法是使用一种称为FlashVars的方法。 FlashVars与在页面之间以HTTP GET参数发送数据的概念非常相似。 实际上,我们正在将数据的键/值对传递给Flex应用程序。

为此,我们需要在HTML中的两个位置添加FlashVars属性。 FlashVars属性的值将是参数对的URL编码列表,例如: name=kai&site=ventego-creative.co.nz&...等。 从上面将其嵌入到代码示例中将获得以下结果:

AC_FL_RunContent( 
 "src", "FlexAndJS",
 ...
 "FlashVars", "name=kai&site=ventego-creative.co.nz" );
...
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
   id="FlexAndJS" width="100%" height="100%"
   codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
 <param name="movie" value="FlexAndJS.swf" />
 ...
 <param name="FlashVars" value="name=kai&site=ventego-creative.co.nz" />

 <embed src="FlexAndJS.swf" quality="high" bgcolor="#869ca7"
     ...
     FlashVars="name=kai&site=ventego-creative.co.nz" >
 </embed>
</object>
 FlashVars data can be easily used in the Flex application by referring to the parameters object in Application.application . For example, to retrieve the content of the variable site that has been passed in via FlashVars , you'd use a snippet similar to the example below in the ActionScript part of your Flex application:

public var theSite:String = Application.application.parameters.site;

Obviously this means of communication between the wrapper and the Flex application is quite inflexible (you're limited to serialized, flat data in key/value-pairs) and fails to provide a two-way communication. Still, FlashVars are quite often used when the application requires (non-critical) data to be passed in at start time.

ExternalInterface

Now we need to introduce a truly bidirectional communication channel between the Flex application and its wrapper: Flash Player's external API, also known as ExternalInterface . The ExternalInterface class is the representation of the external API in ActionScript 3. In earlier versions of Flash (up to version 8) the fscommand function was used to provide access to the external API.

It can be applied in the following use-cases:

  • 检索有关Flex应用程序容器的信息
  • 从Flex中的ActionScript调用并执行容器中的代码
  • 从容器中调用并执行Flex应用程序中的ActionScript代码

外部API是Flash Player在ActionScript 3中利用的子系统。当我在上面的列表中提到“在容器中调用并执行代码”时,我实际上指的是在HTML包装页面中执行JavaScript代码。 因此,我们将介绍一种设置和运行从HTML和JavaScript到Flex和ActionScript的双向函数调用的方法。

在向您展示一些代码之前,让我们谈谈一些很了解的知识:

  1. 首先,有个坏消息:您有时可能难以访问ExternalInterface类。 好消息是,您几乎不会遇到有关大多数现代浏览器上ExternalInterface可用性的问题。 如果客户端浏览器是以下任意一种,都可以:
    • Windows上的Internet Explorer 5+
    • 支持NPRuntime界面的浏览器(例如Firefox 1 +,Safari 1.3 +,Netscape 8 +,Opera 9+)

    建议的检查外部接口可用性的方法是测试ExternalInterface.available的值。 如果可用,它将返回true 。 这个结果实际上忽略了告诉您有关浏览器JavaScript设置的状态(即,是否启用了用户的JavaScript); 它只会通知您,从概念上讲,您的应用程序可以利用外部API。

    请记住,应将以下通用结构应用于ActionScript中的外部API调用:

    if(ExternalInterface.available)  
    {  
     // Execute ExternalInterface calls in here.  
    }

  2. 如果HTML标记(生成的<object><embed>标记)以HTML形式嵌套,则HTML包装中从Flex和ActionScript到JavaScript的ExternalInterface调用将无法工作。

  3. 在Internet Explorer中,如果<object>标记的id属性包含一个可以解释为JavaScript运算符的字符(例如- ),则对包装的Flex / ActionScript调用将无法正常运行。

从Flex调用JavaScript代码

我将演示前面提到的第一个用例:检索容器信息。 让我们看一下使用ExternalInterface类显示其周围容器的navigator.userAgent属性的Flex应用程序:

<?xml version="1.0" encoding="utf-8"?>  
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" verticalAlign="middle" creationComplete="init();">  
 
 <mx:Script>  
   <![CDATA[  
     import mx.controls.Alert;  
 
     private function init():void  
     {  
       if (ExternalInterface.available)  
       {  
         var userAgent:String = ExternalInterface.call(  
             "navigator.userAgent.toString");  
          Alert.show(userAgent, "UserAgent information:");  
        }  
      }  
    ]]>  
  </mx:Script>  
 
 <mx:Button label="display user agent (again)" click="init();" />  
 
</mx:Application>

简单的逻辑封装在init函数中,我们可以看到ExternalInterface.call实际上执行了对HTML包装器的调用。 在这种情况下,我们只是为navigator.userAgent属性调用toString函数。

让我们迈出下一步:如果页面上有一些JavaScript代码想要从Flex应用程序中执行,该怎么办? 实际上,这非常简单, ExternalInterface类的call方法再次为我们完成了这项工作:

...  
<mx:Script>  
 <![CDATA[  
   private function callJavaScript():void  
   {  
     ExternalInterface.call("sayHelloWorld");  
   }  
 ]]>  
</mx:Script>  
...

在这种情况下,我们将为call提供希望执行的JavaScript函数的名称。 包装器中显然必须包含相应的JavaScript函数; 在以下示例中,我们基本上是从Flash Player触发JavaScript警报弹出窗口的显示。 这是JavaScript:

<script type="text/javascript">  
 function sayHelloWorld()  
 {  
   alert("Hello World from JavaScript");  
 }  
</script>

通过ExternalInterface类将参数从ActionScript传递到JavaScript函数的语法非常相似。 参数作为附加参数传递到call方法中:

...  
<mx:Script>  
 <![CDATA[  
   private function callJavaScript():void  
   {      var a:int = 4;  
     var b:int = 4711;  
     var calcResult:int =  
         ExternalInterface.call("doCalculation",a,b);  
   }  
 ]]>  
</mx:Script>  
...

JavaScript函数可能如下所示:

<script type="text/javascript">  
 function doCalculation(number1, number2)  
 {  
   return number1 * number2;  
 }  
</script>

请注意,如果对JavaScript的调用失败,或者您的JavaScript函数没有适当的返回值,则ExternalInterface调用的结果将为null

如果要处理Flash Player中的安全沙箱,则可能会遇到SecurityError异常。 为了避免在开发过程中以及从开发过渡到测试和生产时遇到麻烦,可以采取两种措施:

  1. 在HTML页面的<object><embed>标记中设置allowScriptAccess属性的适当值。
  2. 在现实的环境中进行开发-在(本地)HTTP服务器通过http://协议从(本地)HTTP服务器(例如Apache或IIS)传递到浏览器的页面中构建和测试您的应用程序,而不是在浏览器中使用file://协议前缀。

使用外部API的好处在于,它允许我们使用大多数普通数据类型,以及一些复杂的类型,例如数组。

从HTML和JavaScript调用ActionScript代码

如前所述, ExternalInterface提供了双向通信通道。 因此,我们能够从嵌入到HTML包装程序中的JavaScript代码在Flex应用程序中调用ActionScript代码。 事实证明,此过程要比其他方法复杂一些,因为实际上我们必须设置一些回调处理程序。

让我们再次尝试显示警报弹出窗口。 这次,我们希望使用HTML按钮作为触发器,以在Flex应用程序中显示警报窗口,该窗口本身会显示当前日期和时间。 第一步是回调,因为如果从包装程序发送特定信号,则需要告诉Flex应用程序要运行哪个ActionScript方法。 回调是在Flex应用程序的init方法中创建的:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" ... creationComplete="init();" ...>  
 
 <mx:Script>  
   <![CDATA[  
     import mx.controls.Alert;  
     private var alert:Alert;  
 
     private function init():void  
     {  
       ExternalInterface.addCallback("showAlert", showAlert);  
     }  
 
     private function showAlert(msg:String):void  
     {  
       var now:Date = new Date();  
       alert = Alert.show(msg,now.toLocaleDateString());  
       alert.status = now.toLocaleTimeString();  
     }  
 ]]>  
</mx:Script>  
 
</mx:Application>

上面我们对addCallBack方法的使用公开了可以由JavaScript调用的函数名称"showAlert" ; 然后将调用ActionScript方法showAlert

在HTML页面上,我们定义了将通过单击按钮asAlert来执行的函数,以及获得对Flash电影对象thisMovie的引用所需的其他辅助函数:

<script type="text/javascript">  
 function thisMovie(movieName)  
 {  
   if (navigator.appName.indexOf("Microsoft") != -1)  
   {  
     return window[movieName];  
   }  
   else  
   {  
     return document[movieName];  
   }  
 }  
 
 function asAlert(value)  
 {  
   thisMovie("alertFromFlex").showAlert(value);  
 }  
</script>

如您所见,函数asAlert利用助手函数thisMovie返回对包含我们的Flash电影的HTML DOM元素的引用,并调用其showAlert方法,并传入字符串值。

为了使上面的代码正常工作,您需要确保这一点:传递到thisMovie函数(此处为"alertFromFlex" )中的参数必须与<object>标记的id属性以及name <embed>标签的<embed>属性用于将Flex应用程序嵌入页面中。

请注意,使用JavaScript与Flex应用程序通信时可能会遇到一个潜在的问题:很难预测在页面渲染过程中Flex应用程序将可用的确切时间点。 因此,最好使用可以从ActionScript中查询的浏览器窗口的onload事件将名为jsReady的标志设置为true 。 如果该标志的值为true ,则可以安全地假定页面加载已完成,并且可以在ActionScript中设置回调处理程序。

接下来呢?

尽管本文将帮助您入门,但Flash Player的外部API还有很多其他可能性。 示例是无限的,可能包括复杂的表单元素和Flex内置的控件,这些元素和控件必须嵌入到现有的HTML表单中; Flex中的图像上传控件和管理系统,必须与周围的HTML页面进行交互; 或将您的Flex应用程序连接到现有的第三方JavaScript API中。

在文章中,我提到了使用非HTML页面包装器的可能性。 通常这将是Flash Player ActiveX控件,该控件嵌入在使用其他技术开发的独立应用程序中。 Adobe提供了一些有关如何使用C#和.NET进行此类工作的基本信息。 在richapps.de上可以找到有关将ActiveX控件嵌入到自己的应用程序中的强烈推荐的教程。

另外,如果您认真考虑链接Flex和JavaScript,请确保进一步研究称为Flex / AJAX Bridge的库。 这个名称有点误导,因为它实际上是一个使两种技术之间的通信更容易的库,而只关注Ajax。 它基本上抽象了底层的ExternalInterface调用,使您可以轻松访问在Flex和包装器之间传递甚至复杂的对象(例如,对UI组件的引用)。 只有少数人知道此工具包的存在,但是它随Flex SDK和Flex Builder一起提供。 您可以在frameworks/javascript/fabridge文件夹中找到它。

测试您的知识

还记得这一切吗? 通过进行测验,对本文的内容进行测试 提交答案,就有机会赢得Adobe CS4 Web Premium和Flex Builder 3 Pro的免费副本。 立即参加测验!

From: https://www.sitepoint.com/ajaxify-your-flex-application/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值