web-dev-qa-db-ja.com

JavaScriptの匿名関数のremoveEventListener

メソッドを含むオブジェクトがあります。これらのメソッドは、匿名関数内のオブジェクトに配置されます。次のようになります。

var t = {};
window.document.addEventListener("keydown", function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
});  

(より多くのコードがありますが、これは問題を示すのに十分です)

場合によっては、イベントリスナーを停止します。したがって、removeEventListenerを実行しようとしていますが、これを行う方法がわかりません。他の質問で、匿名関数でremoveEventListenerを呼び出すことはできないことを読みましたが、これはこの状況でも当てはまりますか?

無名関数内にtのメソッドが作成されているため、可能だと思いました。次のようになります。

t.disable = function() {
    window.document.removeEventListener("keydown", this, false);
}

なぜこれができないのですか?

これを行う他の(良い)方法はありますか?

ボーナス情報;これはSafariでのみ機能する必要があるため、欠落しているIEサポート。

85
bitkid

私はそれが匿名機能のポイントであると信じています、それは名前やそれを参照する方法に欠けています。

もし私があなただったら、名前付き関数を作成するか、変数に入れて参照できるようにします。

var t = {};
var handler = function(e) {
    t.scroll = function(x, y) {
        window.scrollBy(x, y);
    };
    t.scrollTo = function(x, y) {
        window.scrollTo(x, y);
    };
};
window.document.addEventListener("keydown", handler);

その後、次の方法で削除できます

window.document.removeEventListener("keydown", handler);   
64
Adam Heath

実際の関数内にいる場合は、関数への参照としてarguments.calleeを使用できます。次のように:

button.addEventListener('click', function() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', arguments.callee);
});

編集:これは、ストリクトモードで作業している場合は機能しません("use strict";

92
Otto Nascarella

厳格モードで動作する Otto Nascarella のソリューションのバージョンは次のとおりです。

button.addEventListener('click', function handler() {
      ///this will execute only once
      alert('only once!');
      this.removeEventListener('click', handler);
});
38
Melle
window.document.removeEventListener("keydown", getEventListeners(window.document.keydown[0].listener));  

いくつかの匿名関数、keydown 1

警告:Chrome Dev Tools&はコードでは使用できませんlink

9

それほど匿名ではないオプション

element.funky = function() {
    console.log("Click!");
};
element.funky.type = "click";
element.funky.capt = false;
element.addEventListener(element.funky.type, element.funky, element.funky.capt);
// blah blah blah
element.removeEventListener(element.funky.type, element.funky, element.funky.capt);

アンディからフィードバックを受け取っているので(かなり正しいが、多くの例と同様に、私はアイデアの文脈的拡張を示したいと思った)、これは複雑さの少ない解説です:

<script id="konami" type="text/javascript" async>
    var konami = {
        ptrn: "38,38,40,40,37,39,37,39,66,65",
        kl: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    };
    document.body.addEventListener( "keyup", function knm ( evt ) {
        konami.kl = konami.kl.slice( -9 );
        konami.kl.Push( evt.keyCode );
        if ( konami.ptrn === konami.kl.join() ) {
            evt.target.removeEventListener( "keyup", knm, false );

            /* Although at this point we wish to remove a listener
               we could easily have had multiple "keyup" listeners
               each triggering different functions, so we MUST
               say which function we no longer wish to trigger
               rather than which listener we wish to remove.

               Normal scoping will apply to where we can mention this function
               and thus, where we can remove the listener set to trigger it. */

            document.body.classList.add( "konami" );
        }
    }, false );
    document.body.removeChild( document.getElementById( "konami" ) );
</script>

これにより、実質的に匿名の関数構造が可能になり、 実際には非推奨のcallee の使用が回避され、簡単に削除できます。

偶発的に:リスナーを設定した直後にスクリプト要素を削除することは、コードを隠すためのかわいいトリックであり、ying索好きな目にとって明白ではありませんでした( 驚きを台無しにします;-)

したがって、メソッド(more simple)は次のとおりです。

element.addEventListener( action, function name () {
    doSomething();
    element.removeEventListener( action, name, capture );
}, capture );
2
Fred Gandt

最新のブラウザでは、次のことができます...

button.addEventListener( 'click', () => {
    alert( 'only once!' );
}, { once: true } );

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters

2
shunryu111

これはすべてを削除するため理想的ではありませんが、あなたのニーズに合うかもしれません:

z = document.querySelector('video');
z.parentNode.replaceChild(z.cloneNode(1), z);

ノードのクローンを作成すると、組み込み(インライン)リスナーを含む、すべての属性と値がコピーされます。 addEventListener()を使用して追加されたイベントリスナーはコピーしません。

Node.cloneNode()

2
user4427511

これに対する最新のアプローチを提供するには:

//one-time fire
element.addEventListener('mousedown', {
  handleEvent: function (evt) {
    element.removeEventListener(evt.type, this, false);
  }
}, false);
1
Jonatas Walker

JavaScript :addEventListenermethodは、指定されたリスナーをEventTarget(Element | document | Window)に登録しますオンと呼ばれます。

EventTarget . addEventListenerevent_type 、handler_function、 Bubbling | Capturing );

マウス、キーボード イベント WebConsoleでのテスト例:

var keyboard = function(e) {
    console.log('Key_Down Code : ' + e.keyCode);
};
var mouseSimple = function(e) {
    var element = e.srcElement || e.target;
    var tagName = element.tagName || element.relatedTarget;
    console.log('Mouse Over TagName : ' + tagName);    
};
var  mouseComplex = function(e) {
    console.log('Mouse Click Code : ' + e.button);
} 

window.document.addEventListener('keydown',   keyboard,      false);
window.document.addEventListener('mouseover', mouseSimple,   false);
window.document.addEventListener('click',     mouseComplex,  false);

removeEventListenerメソッドは、EventTarget.addEventListener()で以前に登録されたイベントリスナーを削除します。

window.document.removeEventListener('keydown',   keyboard,     false);
window.document.removeEventListener('mouseover', mouseSimple,  false);
window.document.removeEventListener('click',     mouseComplex, false);

caniuse

1
Yash

おそらくあなたが何を求めているのかという点で最良の解決策ではありません。イベントリスナーの呼び出しでインラインで宣言された匿名関数を削除するための効率的な方法をまだ決定していません。

私は個人的に変数を使用して<target>を保存し、イベントリスナー呼び出しの外部で関数を宣言します。例:

const target = document.querySelector('<identifier>');

function myFunc(event) {function code;}

target.addEventListener('click', myFunc);

次に、リスナーを削除します。

target.removeEventListener('click', myFunc);

あなたが受け取る最高の推奨ではありませんが、匿名関数を削除するために私が有用だと思った唯一の解決策は、HTML要素を削除してから置き換えることです。より良いVanilla JSメソッドがあるはずですが、まだ見ていません。

0
Shay Connolly

私は同じ問題に出くわしましたが、これは私が得ることができる最高の解決策でした:

/*Adding the event listener (the 'mousemove' event, in this specific case)*/
element.onmousemove = function(event) {
    /*do your stuff*/
};
/*Removing the event listener*/
element.onmousemove = null;

window要素と'mousemove'イベントに対してのみこれをテストしたため、このアプローチにはいくつかの問題がある可能性があることに留意してください。

0
Gark Garcia