作者:Philter 翻译:xiankevin
原文地址http://www.philterdesign.com/blog/archives/000013.html
当花了一些时间熟悉V2组件的事件模型之后,我觉得可以写一些自己的心得,当然更希望对别人有用。
V2组件的事件模型是基于监听器(listener),而不是像V1中基于回调函数(callbacks)。
在Flash MX的V1组件中,比如你可以使用"setClickHandler"将一个函数注册(register):为当组件被点击的时候调用的回调函数。你需要指定包含着个函数的对象,如果你没有指定,Flash会自动在组件的_parent范围内查找这个函数。但这种方法有一些小的局限,因为你必须有让事件触发时调用的一段代码,并且给所有的相应的目标发送这个消息。
Flash MX实际上有一个内建机制用于实现事件监听,就是ASBroadcaster。这是一个允许你快速建立一个事件广播模型的内部对象(mm的帮助文档并没有提到),提供了添加、移除监听对象,并对这些对象广播事件的方法。但被发现存在一些小bug,导致"only every second eventhandler being called, if listeners are removed in the eventhandler"(不是很理解,汗!)。其他也还有另外一些用于克服这个缺点的基于监听器的事件模型。
Flashplayer7仍然支持ASBroadcaster,在将影片导出为Flashplayer7版本的swf时,似乎也修正了这个bug。但注意在Flash MX 2004是AsBroadcaster,这里s小写!
上面扯了这么多目的是引出下面这些——
V2组件实现了一个不用到AsBroadcaster的监听器模型。就是EventDispatcher类(位置在安装文件夹\en\First Run\Classes\mx\events下),用于给UIObject(是所有组件的基础)添加事件广播(在2004中称为"分派(dispatch)")功能。它与AsBroadcaster的工作方式在本质上是相同的。
1) 通过调用EventDispatcher.initialize(dispathingObj)建立一个分派器对象。
2) 调用dispatchingObj.addEventListener("event",listeringObj)和
dispatchingObj.removeEventListener(listeningObj)来添加、移除一个监听器。
3) 调用dispatchingObj.dispatchEvent(eventObj)为这些监听器分派(广播)事件。
有一些细节需要注意:
1) 看起来似乎EventDispatcher基于被注册监听的事件的类型将监听器加以分类。而据我所知Asbroadcaster仅仅将所有的监听器依附于一个监听器组,并为所有监听器广播所有事件——如果一个监听器没有设置特定的事件处理方法则默认事件广播失败。EventDispatcher实际上为每个事件创建了各自的监听器组。这样,当一个特定的事件被分派时,仅仅查找此事件相关的监听器组。这是一个细节的,也是一个重大的差别!
2) 当通过EventDispatcher分派事件时,仅仅传递了一个包含所有你想要传递给监听器内容的属性的"事件对象(event object)"而不是像之前一样需要传递此事件与一大堆的参数。这个对象的一些重要属性有:
"type"-必需的属性,指明你分派的事件。
"target"-可选的属性,允许你向监听器的处理函数中传递一个对象的引用。如果未指明,则默认指向你的分派器对象。
3) 在你的dispatcher传递被事件监听器调用的该事件之前,实际上会先调用一个内部的方法(有些像V1组件中的"click handler"),这让你如果需要可以使dispatcher对它本身做一些处理(所以类似V1组件中的回调模型)。使用这个功能,你需要在你的分派器对象中定义一个以[事件名+"Handler"]命名的方法,比如如果有一个click事件,则应定义为"clickHandler"。它将传递2)中提到的事件对象。
4) dispatcher可以接受Object、MovieClip或者单纯的函数(function)作为监听器。当你使用它们作为监听器的时候,还是会有稍许的差别:
如果使用Object、MovieClip建立监听器,则有两种方法来捕获事件:
a) 在Object或者MovieClip上定义一个与所监听的事件同名的方法。例如,监听click事件,则应建立myObj.click=function(eventObj){//…};
b) 在Object或者MovieClip上定义一个"handlerEvent(eventObj)"。它将成为一个类的接口(interface),通过它你的监听器可以处理相应被分派的事件(event dispatches)。所有被分派的事件都会传出这个方法,也就意味着你必须察看eventObj.type才能知道具体是哪个事件被触发并且执行相应的代码。
那么在使用组件时具体应该如何做呢?这里给出一个简单的例子。假设场景中有一个Button组件,名为"submitBtn",你应该这样做以建立一个监听器对象:
// Listening object contains a function with the same name as
// the dispatched event
var listeningObj:Object = new Object();
listeningObj.click = function(eventObj:Object):Void {
trace("submitted by " + eventObj.target);
}
submitBtn.addEventListener("click",listeningObj);
或者这样:
// Use a central "handleEvent" function to mitigate all events
var listeningObj:Object = new Object();
listeningObj.handleEvent = function(eventObj:Object):Void {
if (eventObj.type == "click") {
trace("submitted by " + eventObj.target);
}
}
submitBtn.addEventListener("click",listeningObj);
或者像V1组件中一样:
// Old school click handler style
submitBtn.clickHandler = function():Void {
trace("submitted by " + this);
}
另外,使用一个普通的函数作为监听器。假设你想要从不同的分派对象监听相同的事件,如果已经建立了包含click方法的监听对象,那么要区分具体是哪个dispatcher分派的事件的唯一的办法就是察看传递的eventObj的target属性。但如果你定义一系列函数作为监听器,你就可以为任何被分派的事件指定具体如何执行。
// Use plain functions as listeners and specify which one
// you want to listen for any given event from any given
// dispatcher
function handleSubmit = function(eventObj:Object):Void {
trace("submitted!");
}
function handleReset = function(eventObj:Object):Void {
trace("reset!");
}
submitBtn.addEventListener("click",handleSubmit);
resetBtn.addEventListener("click",handleReset);
当然你也可以通过为每个dispatcher建立一个对象完成相同的任务。
尽管AS1.0有很多好处,而且本人也很长段时间使用AS1.0,但是在AS2.0出来这么久的时间里也慢慢地开始使用AS2.0,并且发现在结构化编程.
方面还是优势明显的.大过年的献上一些本人自己总结的在AS2.0类中的一些使用技巧.
首先需要声明的是,本篇文章并不是从基础开始讲AS2.0类的语法结构和使用方法,而是取其中常用的一点来讲讲技巧.所以如果您对于AS2.0类的概念一窍不通(原谅我用这个词),那么请看看闪客帝国里的AS2.0教程.我假设您对AS2.0类有一定的了解,在文章中可能对一些细节就一概而过了.
这篇文章主要内容是建立在AS2.0类与库中影片剪辑(MC)链接的基础上的.我们知道,在自定义类中如果扩展为MovieClip的子类,那么可以在库中linkage里的AS2.0类中写上该类的名称,这样就将该自定义类与库中的MC"绑定"在一起了.我们须要定义的一些额外的属性和方法都可以放到类中,而不用写到MC的帧里,这样代码就更加清晰了. 如果您对MC与自定义类的"绑定"有什么不清楚的,请查阅我翻译的如何在FlashMX2004里使用新的面向对象编程方式.
我们的重点就是讲讲绑定MC类(姑且我们这样叫先)的一些实用技巧.我想大部分正使用这种方式的朋友可以也知道其中几个,或者正为技巧里要讲到的方法一筹莫展呢.
为了区分方便,我把库中与自定义链接的MC称为主MC,与之链接的自定义类成为主MC的类.好吧闲话休说.我先把技巧点一一列出来:
1.类中有同名MC,可以直接引用与之链接的MC中的元素.
2.类中使用setInterval方法.
3.类中使用自定义监听器与监听器方法.
4.类中定义本身自带的方法.
5.类中方法重载.
6.private子类也可使用.
7.在MC中调用类中的自定义方法.
1.类中有同名MC,可以直接引用与之链接的MC中的元素.
不知您是不是还在为引用主MC中的实例而苦恼呢?该技巧意思是如果我们在主MC中又创建另一个MC的实例,比如命名为myMC1,那么我们在主MC的类中只要使用private var myMC1:MovieClip;声明一下就可以直接调用了.同样的对于按钮,文本框也同样适用.
2.使用setInterval方法.
在主MC的类中使用setInterval调用类中的自定义方法要用setInterval第二种用法:setInterval(mc_name,"method_name",interval[,parameters...]); 由于调用的是类中的方法,所以正确用法是:setInterval(this,"method_name",interval[,parameters...]); 注意方法名method_name用双引号引起来.
3.类中使用自定义事件与事件方法.
在类中可以自定义事件,关于如何自定义事件请查阅自定义事件——EventDispatcher类基础.该技巧意思是我们可以在主MC的类(类A)中定义另一个类(类B)中广播的方法,然后把类A注册为类B的监听器.这样在事件触发后可以直接调用监听器方法. 而且该方法可以声明为private.
4.类中定义本身自带的方法.
在主MC的类中可以定义比如onRelease,onEnterFrame等自带的事件处理方法.
以上四点技巧总的来说有一个共同特点,那就是代码都放到主MC的类中,这样封装性就比较好.不过在使用第1点技巧时须注意主MC中须要出现该MC,这样影响了类的通用性,可以在差别处用子类来代替.把父类独立出来.
5.类中方法重载.
AS2.0类没有方法重载,但我们可以利用别的方法来完成,请查阅如何在FlashMX2004中实现方法重载,另外还可以使用arguments对象.
6.private子类也可使用.
与JAVA不同,private属性可以在子类中被调用.
7.在MC中调用类中的自定义方法.
在主MC的帧中或子MC中可以直接调用主MC的类中的自定义方法/属性.如果在帧中直接用"method_name([parameters])"就可以了.子MC中使用"_parent.method_name([parameters])"调用.这里有另一个注意点:如果子MC中_parent.gotoAndStop(frame),那么该代码以下的代码是不会执行的.
主要技巧暂时说这么多,这些都是我常用的.希望对您有所帮助.也欢迎补充.
原文地址http://www.philterdesign.com/blog/archives/000013.html
当花了一些时间熟悉V2组件的事件模型之后,我觉得可以写一些自己的心得,当然更希望对别人有用。
V2组件的事件模型是基于监听器(listener),而不是像V1中基于回调函数(callbacks)。
在Flash MX的V1组件中,比如你可以使用"setClickHandler"将一个函数注册(register):为当组件被点击的时候调用的回调函数。你需要指定包含着个函数的对象,如果你没有指定,Flash会自动在组件的_parent范围内查找这个函数。但这种方法有一些小的局限,因为你必须有让事件触发时调用的一段代码,并且给所有的相应的目标发送这个消息。
Flash MX实际上有一个内建机制用于实现事件监听,就是ASBroadcaster。这是一个允许你快速建立一个事件广播模型的内部对象(mm的帮助文档并没有提到),提供了添加、移除监听对象,并对这些对象广播事件的方法。但被发现存在一些小bug,导致"only every second eventhandler being called, if listeners are removed in the eventhandler"(不是很理解,汗!)。其他也还有另外一些用于克服这个缺点的基于监听器的事件模型。
Flashplayer7仍然支持ASBroadcaster,在将影片导出为Flashplayer7版本的swf时,似乎也修正了这个bug。但注意在Flash MX 2004是AsBroadcaster,这里s小写!
上面扯了这么多目的是引出下面这些——
V2组件实现了一个不用到AsBroadcaster的监听器模型。就是EventDispatcher类(位置在安装文件夹\en\First Run\Classes\mx\events下),用于给UIObject(是所有组件的基础)添加事件广播(在2004中称为"分派(dispatch)")功能。它与AsBroadcaster的工作方式在本质上是相同的。
1) 通过调用EventDispatcher.initialize(dispathingObj)建立一个分派器对象。
2) 调用dispatchingObj.addEventListener("event",listeringObj)和
dispatchingObj.removeEventListener(listeningObj)来添加、移除一个监听器。
3) 调用dispatchingObj.dispatchEvent(eventObj)为这些监听器分派(广播)事件。
有一些细节需要注意:
1) 看起来似乎EventDispatcher基于被注册监听的事件的类型将监听器加以分类。而据我所知Asbroadcaster仅仅将所有的监听器依附于一个监听器组,并为所有监听器广播所有事件——如果一个监听器没有设置特定的事件处理方法则默认事件广播失败。EventDispatcher实际上为每个事件创建了各自的监听器组。这样,当一个特定的事件被分派时,仅仅查找此事件相关的监听器组。这是一个细节的,也是一个重大的差别!
2) 当通过EventDispatcher分派事件时,仅仅传递了一个包含所有你想要传递给监听器内容的属性的"事件对象(event object)"而不是像之前一样需要传递此事件与一大堆的参数。这个对象的一些重要属性有:
"type"-必需的属性,指明你分派的事件。
"target"-可选的属性,允许你向监听器的处理函数中传递一个对象的引用。如果未指明,则默认指向你的分派器对象。
3) 在你的dispatcher传递被事件监听器调用的该事件之前,实际上会先调用一个内部的方法(有些像V1组件中的"click handler"),这让你如果需要可以使dispatcher对它本身做一些处理(所以类似V1组件中的回调模型)。使用这个功能,你需要在你的分派器对象中定义一个以[事件名+"Handler"]命名的方法,比如如果有一个click事件,则应定义为"clickHandler"。它将传递2)中提到的事件对象。
4) dispatcher可以接受Object、MovieClip或者单纯的函数(function)作为监听器。当你使用它们作为监听器的时候,还是会有稍许的差别:
如果使用Object、MovieClip建立监听器,则有两种方法来捕获事件:
a) 在Object或者MovieClip上定义一个与所监听的事件同名的方法。例如,监听click事件,则应建立myObj.click=function(eventObj){//…};
b) 在Object或者MovieClip上定义一个"handlerEvent(eventObj)"。它将成为一个类的接口(interface),通过它你的监听器可以处理相应被分派的事件(event dispatches)。所有被分派的事件都会传出这个方法,也就意味着你必须察看eventObj.type才能知道具体是哪个事件被触发并且执行相应的代码。
那么在使用组件时具体应该如何做呢?这里给出一个简单的例子。假设场景中有一个Button组件,名为"submitBtn",你应该这样做以建立一个监听器对象:
// Listening object contains a function with the same name as
// the dispatched event
var listeningObj:Object = new Object();
listeningObj.click = function(eventObj:Object):Void {
trace("submitted by " + eventObj.target);
}
submitBtn.addEventListener("click",listeningObj);
或者这样:
// Use a central "handleEvent" function to mitigate all events
var listeningObj:Object = new Object();
listeningObj.handleEvent = function(eventObj:Object):Void {
if (eventObj.type == "click") {
trace("submitted by " + eventObj.target);
}
}
submitBtn.addEventListener("click",listeningObj);
或者像V1组件中一样:
// Old school click handler style
submitBtn.clickHandler = function():Void {
trace("submitted by " + this);
}
另外,使用一个普通的函数作为监听器。假设你想要从不同的分派对象监听相同的事件,如果已经建立了包含click方法的监听对象,那么要区分具体是哪个dispatcher分派的事件的唯一的办法就是察看传递的eventObj的target属性。但如果你定义一系列函数作为监听器,你就可以为任何被分派的事件指定具体如何执行。
// Use plain functions as listeners and specify which one
// you want to listen for any given event from any given
// dispatcher
function handleSubmit = function(eventObj:Object):Void {
trace("submitted!");
}
function handleReset = function(eventObj:Object):Void {
trace("reset!");
}
submitBtn.addEventListener("click",handleSubmit);
resetBtn.addEventListener("click",handleReset);
当然你也可以通过为每个dispatcher建立一个对象完成相同的任务。
尽管AS1.0有很多好处,而且本人也很长段时间使用AS1.0,但是在AS2.0出来这么久的时间里也慢慢地开始使用AS2.0,并且发现在结构化编程.
方面还是优势明显的.大过年的献上一些本人自己总结的在AS2.0类中的一些使用技巧.
首先需要声明的是,本篇文章并不是从基础开始讲AS2.0类的语法结构和使用方法,而是取其中常用的一点来讲讲技巧.所以如果您对于AS2.0类的概念一窍不通(原谅我用这个词),那么请看看闪客帝国里的AS2.0教程.我假设您对AS2.0类有一定的了解,在文章中可能对一些细节就一概而过了.
这篇文章主要内容是建立在AS2.0类与库中影片剪辑(MC)链接的基础上的.我们知道,在自定义类中如果扩展为MovieClip的子类,那么可以在库中linkage里的AS2.0类中写上该类的名称,这样就将该自定义类与库中的MC"绑定"在一起了.我们须要定义的一些额外的属性和方法都可以放到类中,而不用写到MC的帧里,这样代码就更加清晰了. 如果您对MC与自定义类的"绑定"有什么不清楚的,请查阅我翻译的如何在FlashMX2004里使用新的面向对象编程方式.
我们的重点就是讲讲绑定MC类(姑且我们这样叫先)的一些实用技巧.我想大部分正使用这种方式的朋友可以也知道其中几个,或者正为技巧里要讲到的方法一筹莫展呢.
为了区分方便,我把库中与自定义链接的MC称为主MC,与之链接的自定义类成为主MC的类.好吧闲话休说.我先把技巧点一一列出来:
1.类中有同名MC,可以直接引用与之链接的MC中的元素.
2.类中使用setInterval方法.
3.类中使用自定义监听器与监听器方法.
4.类中定义本身自带的方法.
5.类中方法重载.
6.private子类也可使用.
7.在MC中调用类中的自定义方法.
1.类中有同名MC,可以直接引用与之链接的MC中的元素.
不知您是不是还在为引用主MC中的实例而苦恼呢?该技巧意思是如果我们在主MC中又创建另一个MC的实例,比如命名为myMC1,那么我们在主MC的类中只要使用private var myMC1:MovieClip;声明一下就可以直接调用了.同样的对于按钮,文本框也同样适用.
2.使用setInterval方法.
在主MC的类中使用setInterval调用类中的自定义方法要用setInterval第二种用法:setInterval(mc_name,"method_name",interval[,parameters...]); 由于调用的是类中的方法,所以正确用法是:setInterval(this,"method_name",interval[,parameters...]); 注意方法名method_name用双引号引起来.
3.类中使用自定义事件与事件方法.
在类中可以自定义事件,关于如何自定义事件请查阅自定义事件——EventDispatcher类基础.该技巧意思是我们可以在主MC的类(类A)中定义另一个类(类B)中广播的方法,然后把类A注册为类B的监听器.这样在事件触发后可以直接调用监听器方法. 而且该方法可以声明为private.
4.类中定义本身自带的方法.
在主MC的类中可以定义比如onRelease,onEnterFrame等自带的事件处理方法.
以上四点技巧总的来说有一个共同特点,那就是代码都放到主MC的类中,这样封装性就比较好.不过在使用第1点技巧时须注意主MC中须要出现该MC,这样影响了类的通用性,可以在差别处用子类来代替.把父类独立出来.
5.类中方法重载.
AS2.0类没有方法重载,但我们可以利用别的方法来完成,请查阅如何在FlashMX2004中实现方法重载,另外还可以使用arguments对象.
6.private子类也可使用.
与JAVA不同,private属性可以在子类中被调用.
7.在MC中调用类中的自定义方法.
在主MC的帧中或子MC中可以直接调用主MC的类中的自定义方法/属性.如果在帧中直接用"method_name([parameters])"就可以了.子MC中使用"_parent.method_name([parameters])"调用.这里有另一个注意点:如果子MC中_parent.gotoAndStop(frame),那么该代码以下的代码是不会执行的.
主要技巧暂时说这么多,这些都是我常用的.希望对您有所帮助.也欢迎补充.
