2008-10-07 5 views
15

Ich habe versucht, dies zu tun:Actionscript 3.0 unter Verwendung von Verschlüssen für Event-Handler

root.addEventListener("click", 
    function() 
    { 
     navigateToURL(ClickURLRequest,"_self"); 
    }); 

Und es macht die Ereignis-Listener hinzufügen. Ich Verschlüsse wie verwenden, weil sie in dieser Situation gut funktionieren,

erfordert jedoch auf die ursprüngliche Funktion eine Referenz den Ereignis-Listener zu entfernen, und da ich einen anonymen Verschluss verwendet wird, ist es nicht funktioniert, habe ich versucht:

root.removeEventListener("click", 
     function() 
     { 
      navigateToURL(ClickURLRequest,"_self"); 
     }); 

sowie:

root.removeEventListener("click", function() {}); 

die einzige Art, wie ich es die anonyme Schließung zu Graben war und den Ereignis-Listener bei einer bereits bestehenden Funktion zeigen würde funktionieren gefunden:

function OnClick (e:Event) 
{ 
    navigateToURL(ClickURLRequest,"_self"); 
} 

root.addEventListener("click", OnClick); 
root.removeEventListener("click", OnClick); 

Kennt jemand eine Möglichkeit, anonyme Closures für Event-Handler zu verwenden und trotzdem die Möglichkeit zu haben, sie zu entfernen?

+0

Warum verwenden Sie nicht weakReference? –

Antwort

3

Sie können sich das Schlüsselwort function() als Konstruktor vorstellen und jedes Mal ein neues Objekt (ein Closure) erstellen. Wenn Sie den Abschluss also nur als Parameter erstellen und keinen Verweis irgendwo beibehalten, gibt es keine Möglichkeit, "den gleichen" Abschluss an anderer Stelle zu erhalten.

Die offensichtliche Lösung ist, was Sie nicht mögen, die Funktion vor der Verwendung zu definieren. Natürlich kann es immer noch eine vollständige Schließung und nicht nur eine "statisch-ähnliche" Funktion sein. Definieren Sie es einfach im gewünschten Kontext und weisen Sie es einer lokalen Variablen zu.

+0

Ja, ich stimme Javier zu. Wenn Sie die Referenz nicht beibehalten, können Sie diese Funktion nicht entfernen. –

0

Ich bin mir nicht sicher, ob dies funktionieren wird, aber es ist ein Versuch wert:

root.removeEventListener("click", arguments.callee); 

Weitere Informationen über sie zu finden sind Flex lang ref

+0

Nein JustFoo, das funktioniert nicht. –

36

Hier ist eine generische Art und Weise Ereignis-Listener zu entfernen, die ich verwendet habe auf Produktionsprojekte


addEventListener 
(
    Event.ACTIVATE, 
    function(event:Event):void 
    { 
     (event.target as EventDispatcher).removeEventListener(event.type, arguments.callee)    
    } 
) 
+0

Ich zweite das. Beachten Sie auch, dass Sie im Beispiel einen Tippfehler gemacht haben: "argumnts" – hasseg

+0

Whoops my bad, es ist jetzt behoben;) –

+0

Brilliant! Hätte ich nie selbst daran gedacht. – Martin

0

Es ist nicht zu viel anders als mit einer definierten Funktion, aber vielleicht wird dies Ihre Bedürfnisse erfüllen. Denken Sie daran, dass Funktionen in ActionScript erstklassige Objekte sind, die Sie als Variablen speichern und weitergeben können.

 
protected function addListener() 
{ 
    m_handler = function(in_event:Event) { removeEventListener(MouseEvent.CLICK, m_handler); m_handler=null} 
    addEventListener(MouseEvent.CLICK, m_handler) 
} 
protected var m_handler:Function 
0

nur eine Randnotiz auf dem Code, den ich in einer Woche Reihe von Tutorials auf der Adobe-Website über im Flex kam. Dort sagten sie, dass Sie immer die Konstanten für die Ereignistypen anstelle der Zeichenfolge verwenden sollten. Auf diese Weise erhalten Sie einen Tippfehler. Wenn Sie im Ereignistyp string einen Tippfehler machen (wie zB "clse"), wird Ihr Event-Handler registriert, aber natürlich nie aufgerufen. Verwenden Sie stattdessen Event.CLOSE, damit der Compiler den Tippfehler abfängt.

-1

Ich weiß nicht, was Sie tatsächlich tun, aber in diesem speziellen Beispiel könnten Sie vielleicht eine _clickEnabled globale Variable haben.

Dann in der Event-Handler nur _clickEnabled überprüfen, und wenn es falsch ist nur return sofort.

Dann können Sie das Gesamtereignis aktivieren und deaktivieren, ohne es abzutrennen und wieder anzubringen.

0

Ich fand mich dabei viel, also habe ich das versucht. Scheint gut zu funktionieren.

addSelfDestructiveEventListener('roomRenderer', 'complete', trackAction, 'floorChanged'); 

private function addSelfDestructiveEventListener(listenee:*, event:String, functionToCall:Function, StringArgs:String):void 
{ 
    this[listenee].addEventListener(event, function(event:Event):void 
     { 
      (event.target as EventDispatcher).removeEventListener(event.type, arguments.callee); 
      functionToCall(StringArgs); 
     }) 
} 
2

Ich benutze dies manchmal:

var closure:Function = null; 
root.addEventListener("click", 
    closure = function() 
    { 
     navigateToURL(ClickURLRequest,"_self"); 
    }); 

root.removeEventListener("click", closure); 
7

Wie bereits angedeutet, können Sie den Verschluss von der Kette von Hörern aus dem Inneren des Verschlusses selbst entfernen. Dies wird durch die Verwendung von arguments.callee getan:

myDispatcher.addEventListener("click", function(event:Event):void 
{ 
    IEventDispatcher(event.target).removeEventListener(event.type, arguments.callee); 

    // Whatever else needs doing goes here 
}); 

Dadurch wird der Verschluss in einer einmaligen Hörer der Veranstaltung effektiv drehen, einfach selbst abgenommen, sobald das Ereignis ausgelöst hat. Obwohl es syntaktisch ausführlich ist, ist es eine unglaublich nützliche Technik für die vielen Ereignisse, die wirklich nur einmal feuern (oder die Sie nur einmal interessieren), wie zum Beispiel "creationComplete" in Flex. Ich benutze dies die ganze Zeit beim Herunterladen von Daten, da ich glaube, dass der Rückrufcode inline das Verständnis erleichtert. Es ist wie die asynchrone-ness versteckt weg:

myLoader.addEventListener("complete", function(event:Event):void 
{ 
    /* Even though the load is asynchronous, having the callback code inline 
    * like this instead of scattered around makes it easier to understand, 
    * in my opinion. */ 
}); 

Wenn Sie jedoch auf die Veranstaltung mehrmals hören wollen, wird dies nicht sehr effektiv aus offensichtlichen Gründen. In diesem Fall müssen Sie irgendwo einen Verweis auf den Abschluss speichern. Methoden sind Objekte wie alles andere in ActionScript und können weitergegeben werden. So können wir unseren Code ändern wie folgt aussehen:

var closure:Function; 

myDispatcher.addEventListener("click", function(event:Event):void 
{ 
    closure = arguments.callee; 

    // Whatever else needs doing goes here 
}); 

Wenn Sie den Ereignis-Listener entfernen müssen, verwenden Sie die ‚Schließung‘ Bezug, etwa so:

myDispatcher.removeEventListener("click", closure); 

Offensichtlich ist dies ein abstraktes Beispiel, aber das Verwenden von Verschlüssen wie diesem kann ziemlich nützlich sein. Sie haben jedoch Nachteile, wie weniger effizient als benannte Methoden. Ein weiterer Nachteil ist die Tatsache, dass Sie tatsächlich einen Verweis auf die Schließung speichern müssen, wenn Sie es jemals brauchen. Es muss dann darauf geachtet werden, dass die Integrität dieser Referenz wie bei jeder anderen Variablen erhalten bleibt.

So, während die andere Syntax ihre Verwendungen haben kann, ist es nicht immer die beste Lösung. Es ist eine Sache mit Äpfeln und Orangen.