ActionScript与JavaScript跨域交互方案:使用Flex IFrame库

云舒
云舒
发布时间:2026-10-14 | 3人浏览过
原创

在Adobe Flex开发中,将Flex应用作为组件嵌入Web页面是常见需求。然而,由于安全沙箱限制和DOM层级嵌套(Flex对象内嵌SWF,SWF中再用iframe嵌入HTML),直接调用JS函数或访问父级方法会遇到跨域或上下文丢失问题。本文将基于`flex-iframe`开源库,详细演示如何通过配置MXML页面与目标HTML文件,实现不受路径限制的ActionScript与JavaScript双向数据交互。

原理与准备条件

Flex应用运行在Flash Player虚拟机中,JavaScript运行在浏览器DOM环境中。两者交互的核心是 ExternalInterface API。但在实际部署中,如果HTML文件本身被Flex以 <code:IFrame> 标签嵌入,那么该HTML内部的JS无法直接通过常规的 window.parent 找到外部Flex的全局对象,因为它位于一个深层的iframe嵌套结构中。

核心组件: flex-iframe

  1. Flex-MXML端: 引入Flex-IFrame命名空间,使用 <code:IFrame> 替代标准iframe,该组件会自动处理加载完后的桥接通信。
  2. HTML-JS端: 需要在顶层window上暴露特定的全局变量(如xiSwfUrlStr),并编写对应的JS函数供AS调用。
  3. 通信机制:
    • ExternalInterface.addCallback():允许JS调用AS函数。
    • ExternalInterface.call():允许AS调用JS函数。

真实操作顺序

第1步:创建目标HTML页面 (MyHtml.html)

目的: 构建用于接收Flex调用的本地HTML环境。这是Flex内部iframe要展示的内容。

入口: HTML文件或任意文本编辑器。

动作与参数:

  1. 编写基础HTML结构。
  2. 定义JS回调函数(Flex将通过 `callIFrameFunction` 调用此函数)。
  3. 在JS中预留查找AS全局对象的逻辑(参考下文代码中的 callA 函数)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> 
<head> 
<title>MyHtml.html</title> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
<script language="JavaScript">
// JS主动调用AS函数示例
function callA() {
   // 关键:通过 window.parent.xiSwfUrlStr 获取当前Flex实例所在的ID
   var ifrm = window.parent.xiSwfUrlStr; 
   if (ifrm) {
       // 动态构造ID来寻找外层的swf Object元素 (假设ID为 'test')
       // xiSwfUrlStr 通常是 SWF的ID属性或者唯一标识
       var obj = document.getElementById(ifrm); 
       // 假设我们在Flex里注册的回调函数名为 sayCallBack
       if (obj && obj.sayCallBack) { 
           var result = obj.sayCallBack("Bill"); 
           alert(result);
       } else { 
           alert('无法找到外部对象');
       }
   } else {
       alert('false'); 
   }
} 

// AS会调用这个JS函数
function jsMethod(arr) { 
    alert("as 调用 js 成功,参数为:" + arr[4]); 
    return "执行完成";
} 
</script> 
</head> 
<body> 
<!-- 注意:这里不需要再嵌入SWF!只放普通HTML元素即可 -->
<input type="button" value="点我看效果" onclick="callA()"/> 
</body>
</html>

图1:标准的Flex内部包含iframe的结构示意图(修改后不再在此处重复嵌入SWF)。

第2步:编写MXML主界面代码

目的: 构建Flex主应用,注册JS回调,并通过 flex-iframe 发送请求到内部HTML。

入口: MXML编译器 / Flash Builder。

重要参数: xmlns:code="http://code.google.com/p/flex-iframe/"

  1. 声明 flash.external.ExternalInterface 导入语句。
  2. 在初始化时,使用 addCallback("sayCallBack", ...) 将AS方法映射给JS。
  3. 使用 myIFrame.callIFrameFunction('jsMethod', [...]) 触发HTML内的JS。
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
xmlns:s="library://ns.adobe.com/flex/spark" 
xmlns:mx="library://ns.adobe.com/flex/mx" 
xmlns:code="http://code.google.com/p/flex-iframe/"
creationComplete="initApp()" width="100%" height="100%">
<fx:Declarations></fx:Declarations> 
<fx:Script>
<![CDATA[
import flash.external.*; 
import mx.events.FlexEvent;

public function initApp():void {
   // 1. 注册回调:让JS可以通过 ID.sayCallBack() 调用 AS 的 callBack 方法
   ExternalInterface.addCallback("sayCallBack", callBack);
}

// JS 调用过来的 AS 响应函数
public function callBack(str:String):String{
    label.text = "收到JS数据: " + str;
    return "Hello " + str;
} 

protected function button1_clickHandler(event:MouseEvent):void {
   // 2. AS 直接调用 JS 函数
   ExternalInterface.call('sayHelloWorld', 'Jim');
   
   // 3. AS 调用 iframe 里的 JS 函数 (注意调用方式)
   // flex-iframe 提供了专用的方法来向嵌入的HTML传参并调用函数
   var array:Array = new Array(); 
   array.push("a", "b","c","d","e"); 
   myIFrame.callIFrameFunction('jsMethod', array, 
       function(str:String):void{
           label.text = "JS回调返回: " + str; 
       });
}]]>
</fx:Script>

<s:VGroup width="100%" height="100%">
   <s:Button label="交互测试" click="button1_clickHandler(event)"/>
   <s:Label id="label" text="等待交互..."/>
   
   <code:IFrame id="myIFrame" source="com/MyHtml.html" width="100%" height="300"/>
</s:VGroup>
</s:Application>

第3步:解决“多重嵌套”导致的死循环问题

目的: 消除早期教程中常见的错误——即在HTML里再次用 <object> 标签去嵌入同一个SWF文件。

很多旧版资料建议在被引用的HTML文件中再写一段Flash播放器代码,这不仅冗余,而且会导致性能下降和上下文混淆。正确的做法是:HTML仅仅是一个普通的Web文档,不应当再包含任何SWF对象。

图2:错误的布局对比(右侧显示了多余的SWF嵌入层)。

常见问题排查

  • Security Sandbox Violation: 如果Flex和HTML不在同一域下,确保在HTML同级放置了 crossdomain.xml 且权限设置为 *。
  • 找不到外部对象: 在HTML中使用 document.getElementById(ifrm).sayCallBack() 调用时,需确保 `xiSwfUrlStr` 变量正确指向了承载Flex的Object元素的ID。
  • 返回值不生效: ActionScript调用JS的 call 方法可以同步获取返回值;但通过 callIFrameFunction 传入的第三个参数是一个异步回调函数,适用于长时间运行的任务。

总结

通过合理运用 `flex-iframe` 提供的桥接API以及正确的DOM层级遍历方法,可以实现Flex应用内部HTML片段与外部Flash环境的无缝通信。核心在于理解Flex实例ID的传递机制以及在HTML中正确地定位宿主容器。

以上就是ActionScript与JavaScript交互实例程序修改的详细内容,更多关于ActionScript与JS交互的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表