• AS3和JS互相调用以及防止缓存的小技巧


    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代码:
    <noscript>
      <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="725" height="350" id="VideoCenter" align="center">
      <param name="allowScriptAccess" value="sameDomain" />
      <param name="allowFullScreen" value="false" />
      <param name="movie" value="VideoCenter.swf" />
      <param name="quality" value="high" />
      <param name="bgcolor" value="#ffffff" />
      <embed src="VideoCenter.swf" quality="high" bgcolor="#ffffff" width="725" height="350" name="VideoCenter" align="center" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
      </object>
    </noscript>


    为了使大家思路清晰,我们依照上面的过程一步步讲解:

    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在本地测试时对后面的参数会报错,说找不到文件,放在服务器上它便能够被解析了。
  • 相关阅读:
    从头认识java-5.2 包(package)
    从头认识java-5.1 为什么需要访问权限?
    从头认识java-4.9 枚举类型
    从头认识java-4.8 数组的初始化(2)-可变参数列表
    从头认识java-4.8 数组的初始化(1)
    从头认识java-4.7 构造器初始化(3)
    从头认识java-4.7 构造器初始化(2)
    全局对象:数字对象
    JavaScript的数据类型
    全局对象:String对象
  • 原文地址:https://www.cnblogs.com/fxair/p/1608557.html
Copyright © 2020-2023  润新知