这是我的Flash/AS3代码,位于主类中。
addEventListener(Event.ENTER_FRAME,function(e:Event){
if(findObject == true){
// I want to remove this ENTER FRAME
}
});
这是我的Flash/AS3代码,位于主类中。
addEventListener(Event.ENTER_FRAME,function(e:Event){
if(findObject == true){
// I want to remove this ENTER FRAME
}
});
尝试这个:
e.currentTarget.removeEventListener(e.type, arguments.callee)
在上面的代码中,你不应该这样做。
如果事件的currentTarget
没有removeEventListener()
方法(可能但很少见),那么mgraph的代码有极小的可能无法按照预期工作。从编译器的角度来看,你将尝试动态解析一个通用对象上的方法,这是容易出错的,需要小心处理。这很危险,因为它表明程序员“不知道”她希望处理什么类型的对象,并且是基于假设工作的。假设对于找到解决方案很有用,但对于实施解决方案同样不利。
如果你想要优化某些东西,那么请注意,你所做的方式实际上会在符号表(在编译后的SWF文件中)中创建一个唯一的(冗余的)名称,这会导致SWF文件的压缩更差。
如果你只是作为实验,那么这没问题,但在真正的项目中应避免使用这样的代码。
还有一件事需要注意:与true
常量进行比较是完全没有意义的。如果这样的比较有任何意义(即findObject
可能随时评估为false
),那么if(findObject){...}
是你代码的等效但更短的版本。
最后一件事,希望你知道匿名函数缺少返回类型声明。在你的例子中,这不会真正改变什么,除了你会得到编译器警告。省略类型声明通常是一种不好的风格。
编辑
public function addEventListener(type:String, listener:Function ...):void
{
this._listeners[type].push(listener);
}
public function dispatchEvent(event:Event):void
{
for each (var listener:Function in this._listeners[event.type])
listener(event);
}
public function removeEventListener(type:String, listener:Function, ...):void
{
delete this._listeners[type][listener];
}
public class SomeEvent extends Event
{
private var _target:NotEventDispatcher;
public function SomeEvent(type:String, someTarget:NotEventDispatcher)
{
super(type);
this._target = someTarget;
}
public override function get target():Object
{
return this._target;
}
}
var dispatcher:IEventDispatcher;
try
{
dispatcher = IEventDispatcher(event.currentTarget);
// now you can be sure this object has removeEventListener
dispatcher.removeEventListener(event.type, arguments.callee);
}
catch (error:Error)
{
// but what are you going to do here?
}
但最常见的情况是您订阅了一个冒泡事件,在这种情况下,您不知道是否要取消订阅event.target还是event.currentTtarget - 因为您不知道正在侦听哪个。
我同意wvxvw的观点。
另一种解决问题的方法是使用一个变量来控制您的ENTER_FRAME事件的“状态”:
private var _state:String;
private function init(e:Event):void {
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event):void {
switch(_state) {
case "play":
// do play stuff
// when you want to pause
// goToPause();
break;
}
}
// you can call the method below from a button or whatever you want
private function goToPause():void {
_state = "pause";
// do some stuff here
// when you are done, switch "_state" back to "play"
}
private function goToPause():void {
_state = "pause";
removeEventListener(Event.ENTER_FRAME, loop);
}
然而,使用“_state”来切换事物的好处在于,您不会最终出现一堆需要跟踪的addEventListeners和removeEventListeners(这取决于您的循环有多复杂)。
仅为了与此处提到的其他技术完整性,您正在创建的函数是一个未绑定的闭包,因此您也可以利用该概念引用您的函数和调度程序。
var callback:Function;
var dispacher:IEventDispatcher = this;
addEventListener(Event.ENTER_FRAME, callback = function(e:Event){
if(findObject == true){
dispacher.removeEventListener(Event.ENTER_FRAME, callback);
}
});
应用普通的闭包变量规则。
如果您想稍后删除侦听器,就不应使用匿名函数调用。
public function main():void
{
//...
//some method, where you add event listener
//...
//adding enterFrame event listener
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
//...
}
private function enterFrameHandler(e:Event)
{
if(findObject) // " == true" is not really necessary here.
{
// removing enterFrame listener:
this.removeEventlistener(Event.ENTER_FRAME,enterFrameHandler);
}
}
currentTarget
不是EventDispatcher
的情况。我不明白这种情况在合理的情况下如何发生... - J. HolmesIEventDispatcher
,那么e.currentTarget
就是this
,因为它保证有一个removeEventListener
,因为它是一个IEventDispatcher
。此外,模拟EventDispatcher
的更简单方法只是新建一个EventDispatcher
。除非你特意去尝试破坏事件堆栈--或者故意不满足事件堆栈的依赖关系--e.currentTarget
将始终指向具有定义removeEventListener
的实例...对我来说,这是一个不完整的模拟,而不是解决方案的问题。 - J. HolmesIEventDispatcher
,而是应该代理到一个EventDispatcher
的实例。原生实现利用受保护的成员来克隆事件,并在事件中设置target
和currentTarget
。 - J. Holmes