删除在Actionscript 3中具有匿名函数的侦听器

时间:2010-01-06 12:58:56

标签: flash actionscript-3 events event-handling

up.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

上面的代码为一些MC添加了一个监听器。最初这些方法是匿名的,但是我将它们命名为clickFunc(),以便在我的remove监听器中尝试引用它们。

这是我的删除侦听器代码。这两个片段都在不同的功能中。在remove方法之前调用add listener方法。

up.removeEventListener(MouseEvent.CLICK, clickFunc );
down.removeEventListener(MouseEvent.CLICK, clickFunc);

我一发布这部电影,就会收到此错误:

1120: Access of undefined property clickFunc.

5 个答案:

答案 0 :(得分:5)

首先,您使用两次相同的名称(clickFunc),无法推断出在调用removeEventListener时引用的是哪一个。其次,clickFunc只能在声明它的函数中访问:

function foo() {
    var clickFunc: Function;
    up.addEventListener(MouseEvent.CLICK, 
        clickFunc = function (event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

    // 'clickFunc' available here, so this is possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
}

function bar() {
    // 'clickFunc' is not available here, so this is not possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
    // 1120: Access of undefined property clickFunc
}

如果您需要引用方法(例如,从事件中删除它们),则它们不能是匿名的。如果你需要从几个方法中引用它们,那么它们不应该是一个方法的本地方法(上例中的foo)。他们需要不同的标识符(clickFunc1clickFunc2,如果你愿意的话)。这是我建议的解决方案:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, upClickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, downClickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, upClickHandler);
    down.removeEventListener(MouseEvent.CLICK, downClickHandler);
}

private function upClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

private function downClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

当然,如果像您的示例中那样,方法是相同的,则只能使用一个:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, clickHandler);
    down.removeEventListener(MouseEvent.CLICK, clickHandler);
}

private function clickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

答案 1 :(得分:3)

好的,有几种方法可以做到这一点。这是我认为你想要的第一种方式。

var upAnon:Function;
var downAnon:Function;

up.addEventListener(MouseEvent.CLICK, 
    upAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    downAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upAnon);
down.removeEventListener(MouseEvent.CLICK, downAnon);

这是另一种方式,获得与第一种相同的所需效果和功能。只是更清洁,通常是标准的练习。

function upFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
function downFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

up.addEventListener(MouseEvent.CLICK, upFunction, false, 0, true);
down.addEventListener(MouseEvent.CLICK, downFunction, false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upFunction);
down.removeEventListener(MouseEvent.CLICK, downFunction);

您将使用第一种类型的原因是,如果您在函数内部创建了eventHandler,并且需要在匿名函数内使用该函数中定义的变量。例如,这里我访问anon函数中的var countMe并在mouse_down上递增它,它将递增直到mouse_up被激活。所以每次我点击它,它会从0开始计数直到鼠标开始,然后重新开始。

var anonFunc:Function;

function doThisStuff(event:MouseEvent):void {
    var countMe = 0;

    stage.addEventListener(Event.ENTER_FRAME,
        anonFunc = function (e:Event) {
            countMe++;
            trace(countMe);
        }
    );  
}

function stopCounting(event:MouseEvent):void {
    stage.removeEventListener(Event.ENTER_FRAME, anonFunc);
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, doThisStuff);
stage.addEventListener(MouseEvent.MOUSE_UP, stopCounting);

答案 2 :(得分:2)

这个应该可以工作......只需删除方法名称......

 up.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
    down.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,-1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

答案 3 :(得分:2)

您正在使用弱引用创建事件处理程序(对于最后一个参数传递true)。您可能已经知道,弱引用不会阻止垃圾收集器收集您的函数。但是,除非你在你定义它们的函数范围之外保持对事件处理程序的引用(看起来不像你),处理程序将只有一个弱引用来保持它们活着,所以尽快垃圾收集器运行,无论如何你的处理程序都消失了。最重要的是,您的事件处理程序看起来不像垃圾收集运行时会触发,因此担心删除处理程序有点毫无意义。无论你是否想要它们,它们都会自行消失。

您需要在范围内维护对这些事件处理程序的引用,这些事件处理程序在它们应该触发时仍然存在。完成后,您应该能够使用这些引用将其删除。

答案 4 :(得分:0)

试试这个:

up.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

down.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);