15

私はこれをやってみました:

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

そして、それはイベントリスナーを追加します。この状況でうまく機能するので、クロージャーを使用するのが好きです。

ただし、イベントリスナーを削除するには、元の関数への参照が必要です。匿名のクロージャーを使用したため、機能しません。次のことを試しました。

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

と同様:

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

私がそれが機能することを見つけた唯一の方法は、匿名のクロージャを捨てて、イベントリスナーを既存の関数に向けることでした:

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

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

イベントハンドラーを削除する機能を保持しながら、イベントハンドラーに匿名クロージャを使用する方法を知っている人はいますか?

4

9 に答える 9

36

これは、本番プロジェクトで使用したイベントリスナーを削除する一般的な方法です


addEventListener
(
    Event.ACTIVATE, 
    function(event:Event):void
    {
        (event.target as EventDispatcher).removeEventListener(event.type, arguments.callee)             
    }
)
于 2008-10-07T19:11:53.010 に答える
7

すでに提案されているように、クロージャー自体の内部からリスナーのチェーンからクロージャーを削除できます。これは、arguments.callee を使用して行われます。

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

    // Whatever else needs doing goes here
});

これにより、クロージャーが効果的にイベントの 1 回限りのリスナーになり、イベントが発生すると、クロージャー自体が切り離されます。構文的には冗長ですが、たとえば Flex の「creationComplete」のように、実際には 1 回しか発生しない (または 1 回しか気にしない) 多くのイベントに対して非常に便利な手法です。コールバック コードをインラインにすると理解しやすくなると思うので、データをダウンロードするときは常にこれを使用します。非同期性を隠しているようなものです。

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. */
});

ただし、イベントを複数回聞きたい場合、これは明らかな理由であまり効果的ではありません。その場合、クロージャーへの参照をどこかに保存する必要があります。メソッドは、ActionScript の他のオブジェクトと同様にオブジェクトであり、受け渡すことができます。したがって、コードを次のように変更できます。

var closure:Function;

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

    // Whatever else needs doing goes here
});

イベント リスナーを削除する必要がある場合は、次のように「クロージャー」参照を使用します。

myDispatcher.removeEventListener("click", closure);

明らかに、これは抽象的な例ですが、このようなクロージャを使用すると非常に便利です。ただし、名前付きメソッドよりも効率が悪いなどの欠点があります。もう 1 つの欠点は、必要に応じてクロージャへの参照を実際に保存しなければならないという事実です。次に、他の変数と同様に、その参照の整合性を維持するように注意する必要があります。

したがって、異なる構文には用途があるかもしれませんが、それが常に最善の解決策であるとは限りません。リンゴとオレンジのようなものです。

于 2010-10-08T22:17:20.353 に答える
3

function() キーワードは、毎回新しいオブジェクト (クロージャー) を作成するコンストラクターと考えることができます。したがって、パラメーターとしてのみクロージャーを作成し、どこにも参照を保持しない場合、「同じ」クロージャーを別の場所に保持する方法はありません。

明らかな解決策は、関数を使用する前に定義することです。もちろん、「静的な」関数だけでなく、完全なクロージャーでもかまいません。必要なコンテキストで定義し、ローカル変数に割り当てるだけです。

于 2008-10-07T18:30:30.737 に答える
2

私は時々これを使用します:

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

root.removeEventListener("click", closure);
于 2010-07-07T13:45:47.050 に答える
0

私はこれをたくさんやっていることに気づいたので、これを試しました。正常に動作しているようです。

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);
        })
}
于 2009-06-04T04:05:41.807 に答える
0

アドビ Web サイトの Flex In A Week セットのチュートリアルで見つけたコードに関する補足事項です。そこでは、文字列ではなく、常にイベントの種類に定数を使用する必要があると彼らは言いました。そうすれば、タイプミス保護が得られます。イベント タイプの文字列に入力ミスがあると ("clse" など)、イベント ハンドラーは登録されますが、もちろん呼び出されることはありません。代わりに、Event.CLOSE を使用して、コンパイラがタイプミスをキャッチできるようにします。

于 2008-10-10T13:20:17.947 に答える
0

定義済みの関数を使用するのとそれほど違いはありませんが、おそらくこれでニーズが満たされるでしょう。関数は ActionScript の第一級オブジェクトであり、変数として保存および渡すことができることに注意してください。

保護された関数 addListener()
{
    m_handler = function(in_event:Event) { removeEventListener(MouseEvent.CLICK, m_handler); m_handler=null}
    addEventListener(MouseEvent.CLICK, m_handler)
}
protected var m_handler:関数
于 2008-10-08T18:13:30.787 に答える
0

これが機能するかどうかはわかりませんが、試してみる価値はあります:

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

詳細については、Flex lang refを参照してください。

于 2008-10-07T18:52:46.400 に答える
-1

あなたが実際に何をしているのかはわかりませんが、この特定の例では、おそらく _clickEnabled グローバル変数を持つことができます。

次に、イベント ハンドラー内で _clickEnabled をチェックし、false の場合はすぐにチェックしますreturn

次に、イベントを切り離して再接続することなく、イベント全体を有効または無効にできます。

于 2008-10-17T21:17:53.657 に答える