質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

5942閲覧

JavaScriptのaddEventListenerが複数回追加されるのを防ぎたい。

ingeniero

総合スコア10

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/01/16 09:46

編集2022/01/16 11:11

前提・実現したいこと

JavaScriptのaddEventListenerが複数回追加されるのを防ぎたい。
クリックイベントの削除を行いたい。

発生している問題・エラーメッセージ

ポップアップ自体は、きちんと実装することができたのですが、クリックしたときにポップアップを表示・非表示させる仕組みを書いてる関数が2回目以降に呼びだされた時、addEventListenerが複数回追加されてしまいます。

そのため、関数が2回以上呼ばれた時は、クリックが一度に2回以上押されて、ポップアップが表示されなかったり、ポップアップが消えなかったりします。

該当のソースコード

JavaScript

1function popupExample() { 2 // ポップアップのHTML要素を取得、なければ終了 3 var popup = document.getElementById('js-popup'); 4 if(!popup) return; 5 // ポップアップのそれぞれの要素を取得 6 var blackBg = document.getElementById('js-black-bg'); 7 var closeBtn = document.getElementById('js-close-btn'); 8 var showBtn = document.getElementById('js-show-btn'); 9 10 closePopup(blackBg); 11 closePopup(closeBtn); 12 closePopup(showBtn); 13 14 function closePopup(elem) { 15 if(!elem) return; 16 elem.removeEventListener("click", addToggle); 17 elem.addEventListener("click", addToggle); 18 } 19 20 function addToggle() { 21 popup.classList.toggle('is-show'); 22 } 23} 24

こちらの関数を複数回呼び出しており、調査すると1回目、3回目、5回目のような奇数回の時は、正しく動いております。

それぞれ奇数回の呼び出し時には、クリックを何回してもきちんと動きます。

試したこと

まずは、この関数自体が正しく動いて、ポップアップが表示されることは確認済みです。

ただし、コンソールログを用いてのデバック実行で、関数が2回目以降呼び出された時は、一度のクリックで複数回(呼び出された回数分だけ)クリックされることが判明。

そのため、クリックイベントを消せないかと、removeEventListenerを追加して、テストしたが結果変わらず。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/01/16 10:57

このコードは、ネストなどは合っていますか? (addToggleがpopupExampleの外側にあるのでしたら、popupは取れなくなるはずです)
ingeniero

2022/01/16 11:09

すみません。コードをここのサイトに移す時に、間違えた模様です。 自分のコードではしっかり内側に入ってるので、大丈夫です。 ポップアップ自体は、1回目に関数を呼んだ時は動作するので、コード自体に問題はないと思います。
guest

回答1

0

ベストアンサー

removeEventListenerは、セットしたときと同じ関数インスタンスを指定しないと解除できません。

addTogglepopupExampleの内側にあるということは、popupExampleを実行するたびにaddToggle別のインスタンスが作られる、ということになり、removeEventListenerは全く無意味になります。

(奇数回のときに正常動作するように見えるのは、クラスを奇数回反転させれば、1回反転したのと同じ結果になるからだと思われます)

投稿2022/01/16 11:14

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/01/16 11:16

なお、実用的にはイベントの付け外しで制御するのは面倒なので、イベントはつけっぱなしにして、別に作った状態フラグを切り替えて「フラグの状態によっては何もせず抜ける」、というようにすることが多いです。
ingeniero

2022/01/16 11:37

ありがとうございます。 ご指摘の通り、addToggleをpopupExampleの外側に配置して、全く同じ関数インスタンスを呼び出すことで、無事何回関数を呼び出しても、ポップアップを正常に表示することができました。 感謝しております。 また、実用的な方法までご教授いただきまして大変勉強になりました。 まだまだ初心者なのですが、頑張りたいと思います。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問