2017-02-08 10 views
2

編集可能な複数のコンテンツを保持できるページがあります。コンテンツを編集するたびに何らかのチェックイベントを発生させたいこれを達成するためのremoveEventlistenerが矢印の関数とパラメータで正常に動作しない

私のコードは次のようになります。

// Find all editable elements. 
let allEditableElements = document.querySelectorAll('[contenteditable="true"]'); 

for(let i = 0; i < allEditableElements.length; i++){ 

    //Remove eventListener to prevent duplicate events. 
    allEditableElements[i].removeEventListener('input', (event) => {myClass.myEventMethod(event);}, false); 

    // Add event. 
    allEditableElements[i].addEventListener('input', (event) => {myClass.myEventMethod(event);}, false); 
} 

すべては、これまで正常に動作します。しかし、私はユーザーがコンテンツを編集できると述べました。これには、編集可能な新しいコンテンツをページ自体に追加することも含まれます。その時点でイベントが再度設定されるため、事前にeventを削除しようとしています。

私の質問は、なぜremoveEventListener機能が期待どおりに機能しないのですか?そして、そのように与えられたイベントに名前を付ける方法はありません:私はいくつかの研究を行なったし、コード自体は次のように働くだろうということが分かった。もちろん、

// With eventNameGivenByUser an event could be removed just by its name. addEventListener('eventTriggerName', 'eventNameGivenByUser', function(), [, options]); 

// Find all editable elements. 

let allEditableElements = document.querySelectorAll('[contenteditable="true"]'); 

for(let i = 0; i < allEditableElements.length; i++){ 

    //Remove eventListener to prevent duplicate events. 
    allEditableElements[i].removeEventListener('input', myClass.myEventMethod, false); 

    // Add event. 
    allEditableElements[i].addEventListener('input', myClass.myEventMethod, false); 
} 

しかし、これはパラメータを渡すことなく、このような動的セットアップで必須です...

希望者は、2017年にライブラリを使用しないでいいとまともな方法があると言います。


編集2017年2月8日:興味があるだけのもののために

: ソリューションは、リスナーに任意のパラメータを渡さないことです。

// as you can see there is no (event) and no arrow function either. 
addEventListener('input', myClass.myEventMethod, false); 

は、すべての今しています次のようなメソッドを用意して呼び出すことです:

// The Parameter will be passed through anyway! 
myEventMethod(event) { 

     /** 
     * Do stuff with event parameter. 
     */ 

}; 

その後、リスナーがそのように取り外すことができます。

removeEventListener('input', myClass.myEventMethod, false); 

追記:

私は電子を使用していますし、クロスブラウザのサポートを必要としません。 Chromium: 56.0.2924.87と互換性があります。

よろしく、Megajin

+0

問題は明白ですが、ソリューションを提供するために現実世界のコードが必要です。特にこれは:_ "これはパラメータを渡すことなし" _問題のコードはパラメータを渡しません。よりよいアプローチが問題を完全に排除することは言うまでもない。 – zeroflagL

+0

@zeroflagLもちろん、リスナーを新しく作成した要素に追加する代わりに、リスナーをすべて実行するという問題を解決できます。 'element.hasEvent()'のような良い方法があるのなら、私はちょっと不思議でした。 – Megajin

答えて

2

removeEventListenerメソッドは、削除するイベント名とリスナー関数の少なくとも2つの引数をとります。あなたの最初の例で

allEditableElements[i].removeEventListener('input', (event) => {myClass.myEventMethod(event);}, false); 

以前にイベントリスナーとして添付されていなかった新しい関数を定義しているので、それは削除することはできません。

私はあなたの第二の試みが悪いのか分からない:

allEditableElements[i].removeEventListener('input', myClass.myEventMethod, false); 

この1つが正常に動作する必要があります。しかし、両方のアプローチを組み合わせることができます。クラスメソッドを関数にラップし、ラップされたバージョンをリスナーとしてアタッチします。あなたはただ、後で削除することを可能にするための基準を持っている必要があります。

const inputListener = (event) => { myClass.myEventMethod(event); }; 
let allEditableElements = document.querySelectorAll('[contenteditable="true"]'); 


for(let i = 0; i < allEditableElements.length; i++){ 

    //Remove eventListener to prevent duplicate events. 
    allEditableElements[i].removeEventListener('input', inputListener, false); 

    // Add event. 
    allEditableElements[i].addEventListener('input', inputListener, false); 
} 

私はちょうどイベントの委任を使用することをお勧めすると述べたことすべて。 DOM内の要素が高いアップにリスナーを添付して、新しい要素が表示されたときにイベントリスナーをクリアして再追加を心配しないでください:

const handleContentEditable = e => { 
    if(e.target.isContentEditable){ 
     console.log('editing ', e.target); 
    } 
}; 

document.body.addEventListener('input', handleContentEditable); 

https://jsfiddle.net/rd3y9gh9/1/

+1

@Kaiidoはチェックを「e.target.isContentEditable」に更新しました。ありがとうございます。 – pawel

+0

うわー...あなたの答えをありがとう私はあなたの助けを借りて解決策を見つけました。リスナーの宣言中にパラメータ '(event)'を渡す必要はありません...とにかくパラメータは渡されます。そして、イベントの代表団のおかげで、私はそれも見ていきます。 +1と受け入れられた答え! – Megajin

2

にremoveEventListenerの矢印機能は、新しい関数の参照を作成しているためです。 removeEventListenerには、addEventListenerに渡された元のメソッドへの参照が必要です。

あなたのケースでイベントメソッドへの参照を保持するか、入力エレメントを即座に再作成する必要があります。これにより、すべてのイベントリスナーが削除されます。あなたはおそらく、元の要素のクローンを作成し、それを置き換えるためにそれを使用できるよう

https://developer.mozilla.org/en/docs/Web/API/Node/cloneNode

クローンノードは、イベントリスナーをコピーしません。

+0

あなたの答えをありがとう、私はそのための矢印機能+1について考えていませんでした。しかし、私は解決策を見つけました。リスナー関数に 'event'パラメータを渡す必要はありません。 – Megajin

関連する問題