AS3的精典功能经验技巧

在L4cd的BLOG上看到几个比较好的文章,现在整理一下,统一发布,感谢Lc4d共享他的经验
 

1.getDefinition - 模块化你的程序

为了加快程序的加载..
我们通常会把不同的功能模块做成不同的swf,要需要的时候再进行加载.

开始的时候..我们通常会直接使用loader加载,,然后用addChild把loader显示出来..
这样就完成了最简单的"模块"化了..

当然进一步..我们会发现上面的方法已经满足不了我们的需求..
有时候我们需要的不是一个实例对象,我们想得到的是一个类..让我们可以像调用自身库中的类一样可以实例化..复制..等等

这时候我们就可以使用ApplicationDomain(应用程序域),把加载进来的swf中的库的东西当自己的库一样使用

概念性的东西还是不好说...
直接看代码吧..下面的代码就是一个最简单的例子
 

  1. //还是需要loader先进行加载   
  2. var loader:Loader = new Loader()   
  3. loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderComplete)   
  4.   
  5. //sub.swf是一个外部swf,该swf库里有一个链接名叫"k_abc"元件   
  6. loader.load(new URLRequest("sub.swf"))   
  7.   
  8. function loaderComplete(e:Event):void{   
  9.     //创建一个应用程序域   
  10.     var app:ApplicationDomain = loader.contentLoaderInfo.applicationDomain   
  11.     //使用getDefinition返回sub.swf的库中链接名为k_abc的Class   
  12.     var c:Class = app.getDefinition("k_abc") as Class   
  13.   
  14.     //接下来就不多说了..像普通的类一样操作就


2.AS3中for循环创建(复制)对象


在as2中,我们经常使用for来创建或复制多个相同的对象,
到了as3,由于建立对象的方法的改变,以前的方法已经不适用了.
今天介绍一下as3的方法:
方法常用的有两种,
第一种适用所有的对象,方法是先建一个数组,然后把建立的对象的引用指定对数组相应的索引
第二种适用显示对象,其实在as3中,都应该用这种方式,就是给对象指定name,然后使用getChildByName的方式来引用该对象.

  1. //通用的方法,适用所以对象   
  2. var obj:Array = new Array()   
  3. for(var i:uint=0;i<10;i++){   
  4.     var m:MovieClip = new MovieClip()   
  5.     addChild(m)   
  6.     obj["mc"+i] = m   
  7. }   
  8. trace(obj["mc1"])   
  9.   
  10. //适用显示对象   
  11. for(var k:uint=0;k<10;k++){   
  12.     var mm:MovieClip = new MovieClip()   
  13.     mm.name = "mc"+k   
  14.     addChild(mm)   
  15. }   
  16. trace(getChildByName("mc1"))  


另外,有时候我们会遇到这样的情况
var obj0:MC0 = new MC0()
var obj1:MC1 = new MC1()
var obj2:MC2 = new MC2()
var obj3:MC3 = new MC3()

这个时修,我们可以使用getDefinitionByName,用字符串返回类
 

  1. for(var i:uint=0;i<4;i++){   
  2.     var _class:Class = getDefinitionByName("MC"+i) as Class   
  3.     var m = new _class()   
  4.     addChild(m)   
  5. }  

 


3.代理类

对于代理类,它的作用就是在不能传参数的时候帮助你传参数,什么时候不能传参数,
像:
addEventListener(Event.COMPLETE,function)
这个时候如果我们需要给function参指定的参数以达到不同的效果,就需要用到代理..,我们看看以下的用了代理函数的代码
addEventListener(Event.COMPLETE,getFun(function,args))

这样,我们就可以在本来不可以传参的情况下传送参数.其中getFun就是代理函数.(一般网上都已经直接写成了代理类),getFun会帮我们把function,args生成一个无参数的函数再传给addEventListener,那么我们原来的function只需要写成
function(e:Event[,参数]):void{
  //代码
}
就可以了

  1. function getFun(_function:Function,...alt):Function{   
  2.     var _fun:Function = function (e:*):void {   
  3.         var _alt:Array = new Array()   
  4.         _function.apply(null,_alt.concat(e,alt));   
  5.     };   
  6. return _fun;   
  7. }  

 

4.让对象removeChild时自动删除子对象/属性/侦听

在AS3里..我们无法手动完全删除一个对象,,
以MovieClip为例..
我们只有在删除它的时候
除了removeChild(对象)外
还必须清空它的子对象
删除所有动态添加的属性
删除所有侦听
删除所有引用
然后等待垃圾回收,

可是实际操作的时候..
在长长的代码当中..经常会忘记自己什么时候写了侦听..什么时候添加了动态属性

其实,,我们可以借用显示对象中的Event.REMOVED,在删除对象的时候,让对象自己调用删除函数,删除相关的东西

下面这个类继承了MovieClip,当他的实例在removeChild的时候,对象将"自我毁灭"

  1. package net.L4cd.display{   
  2.     import flash.display.MovieClip;   
  3.     import flash.events.Event;   
  4.     dynamic public class iMovieClip extends MovieClip{   
  5.         private var lis:Array;//定义一数组保存侦听   
  6.         public function iMovieClip(){   
  7.             lis = new Array()   
  8.             addEventListener(Event.REMOVED,remove)//侦听删除事件   
  9.         }   
  10.            
  11.         //重写addEventListener,在增加侦听的时候..把相应的事件保存到数组   
  12.         override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void{   
  13.             lis.push([type,listener,useCapture])   
  14.             super.addEventListener(type,listener,useCapture,priority,useWeakReference)   
  15.         }   
  16.            
  17.         //"自我毁灭"的方法   
  18.         private function remove(e:Event):void{   
  19.             if(e.currentTarget != e.target)return  
  20.             stop()   
  21.             //删除子对象   
  22.             trace("删除前有子对象",numChildren)   
  23.             while(numChildren > 0){   
  24.                 removeChildAt(0)   
  25.             }   
  26.             trace("删除后有子对象",numChildren)   
  27.                
  28.             //删除动态属性   
  29.             for(var k:String in this){   
  30.                 trace("删除属性",k)   
  31.                 delete this[k]   
  32.             }   
  33.                
  34.             //删除侦听   
  35.             for(var i:uint=0;i<lis.length;i++){   
  36.                 trace("删除Listener",lis[i][0])   
  37.                 removeEventListener(lis[i][0],lis[i][1],lis[i][2])   
  38.             }   
  39.             lis = null  
  40.         }   
  41.     }   
  42. }  

然后我们另外新建一个flash,直接在时间轴上写下以下代码

  1. import net.L4cd.display.iMovieClip;   
  2. var mc:MovieClip = new iMovieClip()   
  3. mc.addEventListener(Event.ADDED,aaaa)   
  4. mc.addEventListener(Event.ADDED_TO_STAGE,aaaa)   
  5. mc.addEventListener(Event.ENTER_FRAME,aaaa)   
  6. mc.addEventListener(MouseEvent.CLICK,aaaa)   
  7. mc.addEventListener(MouseEvent.MOUSE_DOWN,aaaa)   
  8. mc.a = "http://L4cd.Net"  
  9. mc.b = "我是动态属性2"  
  10. mc.name = "我是MC"  
  11. addChild(mc)   
  12. function aaaa(e:Event){   
  13.        
  14. }   
  15. removeChild(mc)   
  16. mc = null  

运行后.,,输出框就会出现

  1. 删除前有子对象 0   
  2. 删除后有子对象 0   
  3. 删除属性 b   
  4. 删除属性 a   
  5. 删除Listener removed   
  6. 删除Listener added   
  7. 删除Listener addedToStage   
  8. 删除Listener enterFrame   
  9. 删除Listener click   
  10. 删除Listener mouseDown  

这样,,,我们能做的事都已经做完了..等垃圾回收进行回收就ok了

上面的remove方法就是mc在移除的时候,对自己进行的清理,,
注意的是,以上只针对MovieClip进行的清理,每个类或你自定义的类都有不同..
如Sprite不需用要stop(),不需要删除动态属性..等等..
这个就由你自己去发挥~
写一组自己的"自我毁灭"类..

还有需要注意的是..像有时候,你只想removeChild,而不想进行删除,这样可以把上面的代码进行修改.
把remove设置为公开的方法
然后把addEventListener(Event.REMOVED,remove)去掉..
最后在你想删除对象的时候,,,再调用remove()就ok了..

 

5.自定义双击事件 - iDoubleClick

flash从as3开始支持双击事件..
我们只需要使用对象.doubleClickEnabled = true,再侦听MouseEvent.DOUBLE_CLICK事件~
就可以使用双击事件
可是发现了一个不足的地方..
如果我们同时侦听双击跟单击事件,,
那当双击的时候.就会出现两个事件同时发生..
这种情况实在不是很符合我们一般的需求..

看来还是要用as2的老办法,用单击间的延时..来判断单击与双击..不过由于as3的事件机制~~
我们完全可以模拟发现双击..


直接看看应用代码
 

  1. //导入类   
  2. import net.L4cd.*;   
  3. //启用双击事件,注意一下.这里的200是指两次点击之前的延时.   
  4. iDoubleClick.enable(mc,200)   
  5.   
  6. //另外可以使用  iDoubleClick.disable(mc)   来取消自定义双击   
  7. //像平常一样侦听   
  8. mc.addEventListener(MouseEvent.DOUBLE_CLICK,mcDouClick)   
  9. mc.addEventListener(MouseEvent.CLICK,mcClick)   
  10. function mcClick(e:MouseEvent):void{   
  11.     trace(e)   
  12. }   
  13. function mcDouClick(e:MouseEvent):void{   
  14.     trace(e)   
  15. }  


注意使用了自定义事件后就不要使用doubleClickEnabled = true,以免冲突然

 




评论: 2 | 引用: 0 | 查看次数: 1611
回复回复aaron[2010-01-04 08:38 PM | del]
迷离
谢谢你一直关注我 呵呵

你说的第二点可能是没有理解到我说的意思
当一个序列类而不是一个类的时候会用到 比如 : Class1  class2  class3
这三个类要用一个for来创建的时候就会用到我说的方法了


还有 图文混排我为此表示抱歉 没有研究透彻就说出了大话 哈哈  本来是有思路的 但是后来我试了一下 确实不行 只能用CS4的排版了  呵呵 这么久才回复你 不好意思哈
回复回复迷离[2009-04-17 11:09 AM | del]
第一点的应用程序域不错,学到了.

第二点的复制我是将每个新类加到数组里的,然后访问数组节点来得到该类
var array:Array=new Array();
for(var i=0;i<=10;i++){
var c:Class=new Class();
array.push(c);
}
array[0].....array[9],这样调用就OK了.哈哈,没那么复杂吧.

还有,你说写的图文混排还没有出来呀?快给我出来.
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭