ActionScript与JavaScript跨域交互方案:使用Flex IFrame库
在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
- Flex-MXML端: 引入Flex-IFrame命名空间,使用
<code:IFrame>替代标准iframe,该组件会自动处理加载完后的桥接通信。 - HTML-JS端: 需要在顶层window上暴露特定的全局变量(如xiSwfUrlStr),并编写对应的JS函数供AS调用。
- 通信机制:
ExternalInterface.addCallback():允许JS调用AS函数。ExternalInterface.call():允许AS调用JS函数。
真实操作顺序
第1步:创建目标HTML页面 (MyHtml.html)
目的: 构建用于接收Flex调用的本地HTML环境。这是Flex内部iframe要展示的内容。
入口: HTML文件或任意文本编辑器。
动作与参数:
- 编写基础HTML结构。
- 定义JS回调函数(Flex将通过 `callIFrameFunction` 调用此函数)。
- 在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/"
- 声明
flash.external.ExternalInterface导入语句。 - 在初始化时,使用
addCallback("sayCallBack", ...)将AS方法映射给JS。 - 使用
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交互的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









