[quote]AS3和JS的互相调用网上一搜能搜到很多,我确实也是这么做的。然而结果却并非令人满意,大部分都是抄子chm帮助手册,或者是叙述得不明白。于是我又手痒了,写篇详细易读的出来,连带分享一个防止缓存的小技巧。
在这里我要先描述一下功能的需求:写死swf文件,读取xml的配置信息,仅靠修改页面上的js代码来改动所需要的xml文件url,并防止缓存。
—
第一步,建立flash as3文件,之后它就不需要改动了,只要编写它的文档类并发布就行。这里我将.fla文件命名为Test.fla,文档类关联为Test.as。
首先我们来展示下AS3中调用JS的方法,这是最简单的事情,简单到只需一句话便可。
AS3的Test.as文档类:
package {
import flash.display.Sprite;
import flash.external.ExternalInterface;
public class Test extends Sprite {
public function Test() {
callJavaScriptFunction();
}
private function callJavaScriptFunction():void {
if(ExternalInterface.available) {
ExternalInterface.call("sayHello", "army");
}
}
}
}
发布页面中的JS代码:
function sayHello(name) {
alert("hello, " + name);
}
as代码很简单,文档类Test继承Sprite,构造函数中执行定义的callJavaScriptFunction()方法。先要说明下ExternalInterface这个类,它在flash.external包下,官方的解释是“在 ActionScript 和 Flash Player 的容器之间实现直接通讯的应用程序编程接口,例如,含有 JavaScript 的 HTML 页。”,可以说是标准的通信接口,只要是和JS互相调用,都要用到它。
在callJavaScriptFunction()方法中,先是判断ExternalInterface.available属性,当外部接口可调用时,执行ExternalInterface类的call方法,它接收若干个参数。第一个是调用的js方法名,后面依次是传给所调用js方法的参数。在这里ExternalInterface.call(“sayHello”, “army”)就相当于执行了js代码中的sayHello(“army”)方法。如你所见,页面中的确弹出了一个窗口,内容正是传过来的”army”。
需要注意的是,js代码段必须写在嵌入的swf段前面,因为这样才能确保执行之前js全部载入了,否则的话可能会出现无法执行的情况。
—
接下来我们来看看从JS中调用AS的方法。这里我先提个问题:由于放在网络上,swf文件的下载时间是个未知数,如何才能确保js调用as的时候swf已经加载完成了呢?
我所使用的是一个小技巧:依旧是js片段写在swf前面,先在swf里面调用js方法,然后所调用的js方法里再返回去调用as的方法。这样就可以确保swf加载完成并能顺利执行了,整个过程如下:
js片段首先被浏览器读取并加载 =》 浏览器读取swf文件直至完成 =》 swf调用js的方法 =》 被调用的js方法中去调用swf中的as方法。
AS3的Test.as文档类:
package {
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.text.TextField;
public class Test extends Sprite {
public function Test() {
callJavaScriptFunction();
}
private function callJavaScriptFunction():void {
if (ExternalInterface.available) {
ExternalInterface.addCallback("callAsFunction", onCallBackHandler);
ExternalInterface.call("callBackBridge");
}
}
private function onCallBackHandler(s:String):void {
var textField:TextField = new TextField();
textField.text = s;
addChild(textField);
}
}
}
发布页面中的JS代码:
function getSwfInstance(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName];
} else {
return document[movieName];
}
}
function callBackBridge() {
getSwfInstance("Test").callAsFunction("Hello, army!");
}
页面html代码:
为了使大家思路清晰,我们依照上面的过程一步步讲解:
1.js片段首先被浏览器读取并加载
2.浏览器读取swf文件直至完成
这两步没啥好说的,浏览器打开页面就会读取,不关我们的事情。
3.swf调用js的方法
我们看到Test.as中的构造函数依旧调用了callJavaScriptFunction()方法,不过这个方法已有所改变。先是判断ExternalInterface.available属性,然后addCallback()注册一个监听器,再调用js的callBackBridge()方法。
注意监听器必须先注册,这个监听器就是为了js回调as时而注册的,当回调发生时,这个监听器就会被激活,进而执行监听的方法。在这里我们监听js的callAsFunction()方法,并设定回调方法为as的onCallBackHandler()。
4.被调用的js方法中去调用swf中的as方法
由于swf里调用了js的callBackBridge()方法,因此会执行它。callBackBridge()方法内部先是用getSwfInstance()方法取得页面中的swf对象(根据浏览器不同而取得方法不同),然后调用取得对象的callAsFunction()方法,并传递了参数。
由于js中callAsFunction()方法被调用,因此as中注册的监听器监听到了方法名”callAsFunction”,并把它转到回调函数onCallBackHandler()上。因此js中执行callAsFunction(“Hello, army!”)就相当于as中执行了onCallBackHandler(“Hello, army!”)一样。
结果不出所料,as的onCallBackHandler(“Hello, army!”)方法被执行,在swf上生成一个文本片段,片段内容正是传递过来的参数”Hello, army!”。
—
结尾的地方我要分享一个防止缓存的小技巧,也就是文章开头所说的功能需求。
通过as调用js方法,再让js回调as方法的这么一个办法,我们可以写死swf文件,通过修改页面中的js代码参数来让swf读取不同的xml配置文件。如果你看懂了上面的说明并亲自动手实践成功了,那么只需做小小修改便能完成这个需求。
接下来的问题是,假如我的xml文件名不想改动,怎么样才能防止缓存呢?
一种办法就是在as的urlloader中读取urlrequest时在xml文件末尾加上随机数,这是自动的办法;另一种就是手动修改js回调函数中的参数,在.xml文件后面加上唯一的随机参数,如:config.xml?1。每更新一次xml文件,就将那个参数+1,如此便能手动防止缓存。
值得一提的是,urlrequest在本地测试时对后面的参数会报错,说找不到文件,放在服务器上它便能够被解析了。
[/quote]
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net