AS3中的removeEventListener无法正常工作

4
这让我很疯狂。为什么removeEventListeners不起作用呢?
类构造函数
public function item(brand:String, title:String, price:Number, mp:Number, 
       path:String, sb1:*, sb2:*):void

sb1:*和sb2:*是对象钩子。

这些是指定的监听器:

_sb1.addEventListener("Changed", slideBarChanged); // Price
_sb2.addEventListener("Changed", slideBarChanged); // MegaPixels

这个函数被称为:

private function slideBarChanged(e:Event):void
{           
switch(e.target.type)
{
    case "Price": 
        if(int(e.target.currVal) > Math.abs(this.price))
        {
            this._active = false;
            _sb2.removeEventListener("Changed", slideBarChanged);
        }
        else {
            this._active = true;
            _sb2.addEventListener("Changed", slideBarChanged);
        }
        break;

    case "MegaPixels": 
        if(int(e.target.currVal) > Math.abs(this.mpixels))
        {
            this._active = false;                           
            _sb1.removeEventListener("Changed", slideBarChanged);
        }
        else { 
            this._active = true;
            _sb1.addEventListener("Changed", slideBarChanged);
        }
        break;          
}

一切都运作正常,但是当项目变为“_active = false”时,监听器没有被移除;实际上,应该按照以下方式工作:

如果价格太高,则忽略像素并只关注价格。 如果像素太高,则忽略价格并只关注像素。

这让我感到困惑,非常感谢您的帮助。 谢谢。


我认为首先要做的事情是分离函数。有一个megapixelChange和一个priceChange函数。此外,只有一个“this._active”。你怎么知道哪个是活动的?这可能与您的case语句有关,在那里您永远无法达到适当的“removeEventListener”。 - Glenn
你是否曾经创建过对象钩子的新实例并将其分配给_sb1和_sb2? - Allan
8个回答

4
尝试一下。
e.target.removeEventListener("Changed", slideBarChanged); 

与之相反
_sb1.removeEventListener("Changed", slideBarChanged); 

或者

_sb2.removeEventListener("Changed", slideBarChanged);

另外需要注意的是,你应该解析一个常量而不是字符串字面量作为addEventListener()和removeEventListener()方法的类型参数。

const CHANGED:String = "changed";

_sb1.addEventListener(CHANGED, slideBarChanged); 
_sb1.removeEventListener(CHANGED, slideBarChanged); 

1

好的,以防有人希望得到答案,这就是我所做的。

简化

现在逻辑看起来像这样,并且它完全按照我的意愿工作。

private function slideBarChanged(e:Event):void
{           
 if((int(this._sb1.currVal) > Math.abs(this._price)) || (int(this._sb2.currVal)) > Math.abs(this._mpixels))
 {
  this._active = false;
 }
  else this._active = true;
}

感谢您的所有帮助 - 非常感激。


1

您正在多次添加事件侦听器。删除侦听器可能无法完全删除它。

在以下示例中:

else {
    this._active = true;
    _sb2.addEventListener("Changed", slideBarChanged);
}

你可以使用.hasEventListener添加额外的条件,或者使用我更喜欢的方法。在添加事件侦听器之前,先删除该行上的事件侦听器。这很傻,但如果你在每个实例中尝试在添加侦听器之前删除它,你将永远不会重复。此外,如果您尝试删除不存在的侦听器,Flash会默默地忽略您。

在Flex中,通过一些Flex特定的处理方式解决了多个侦听器的问题,但在Flash中仍然会出现。


0
也许我还没有完全理解所有的代码,但是如果我要猜的话,我会说可能是你对象的类型声明引起的问题。例如:
sb1:*, sb2:*

如果你将它们改成什么会发生:

sb1:IEventDispatcher, sb2:IEventDisptacher

无论如何都很容易尝试。


仍未删除监听器。 - Steve

0

Adobe的文档显示:

从EventDispatcher对象中移除一个侦听器。如果没有在EventDispatcher对象中注册匹配的侦听器,则调用此方法无效。

可能它找不到它。

RemoveListner方法是:

public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void

在调用方法时,您可能需要添加 useCapture。

useCapture:Boolean (default = false) — 指定侦听器是在捕获阶段、目标阶段还是冒泡阶段注册的。如果侦听器同时在捕获阶段和目标阶段以及冒泡阶段注册,则需要两次调用 removeEventListener() 来删除它们,一次使用 useCapture() 设置为 true,另一次使用 useCapture() 设置为 false。


0

我是CasaLib的忠实粉丝。这个库有很多基础库被扩展了,其中之一就是RemovableEventDispatcher

你可以尝试使用这个库,看看是否有所帮助。


0
你尝试使用willTrigger()方法来确定监听器是否真正活动吗?还有,你尝试在那里运行跟踪以确保你的代码实际被调用了吗?

就像我在原帖中所说的,一切都按设计工作,但是监听器没有被移除。 - Steve
我建议编写一个FlexUnit测试用例,以证明监听器未被移除。请参阅:http://pastebin.com/NMqKyN0N - Naftuli Kay

0

在您展示的代码中,分配和删除监听器的方式似乎没有问题。我会怀疑以下几点:

a) Flash 中的标准 UI 元素使用 Event.CHANGE 常量传播更改,该常量解析为字符串 "change",而您的所有监听器都被分配给了 "Changed"。如果您只是一次添加了原生的 "change" 监听器,则每当值更改时,事件侦听器将正确地被调用,但 removeEventListener ("Changed",...) 将永远不起作用。无论如何,当您分配或删除侦听器时,应始终使用字符串常量,以避免拼写错误。

b) 您的 event.target 未解析为实际的 slideBar 对象,而是使用 bubbling 事件的某个嵌套的 DisplayObject

c) 您的 slideBar 的舞台实例与 _sb1 和 _sb2 中引用的对象不同。如果您在某个时刻创建了新的 slideBar 实例,但从未更新该项的变量,则可能会发生这种情况。为避免这种情况,您可以使用 event.target.removeEventListener() 而不是直接定位 _sb1 或 _sb2。

d) 您的逻辑存在问题。您确定 removeEventListener 调用是否被执行过吗?也许 if 语句从未评估为真?如果比较的任一侧为 NaN,或者 slideBar 值计算有误,可能会出现这种情况。

我也不明白为什么您要完全删除监听器 - 看起来您正在创建某种过滤机制,虽然如果项目不在指定范围内,则将 this._active 设置为 false 是有意义的,但您仍需要侦听 slideBar 更改以在稍后重新激活它。


不使用标准UI,而是使用我自己的slideBar类,在鼠标松开时分派更改事件。 - Steve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接