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

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

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

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

意見交換

クローズ

3回答

996閲覧

JavaScriptの`addEventListener`はその都度書くべきか?分岐すべきか?

origa3

総合スコア22

JavaScript

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

0グッド

1クリップ

投稿2023/02/11 04:41

編集2023/02/11 05:47

0

1

テーマ、知りたいこと

JavaScript のaddEventListener
・その都度書きますか?
・中で分岐しますか?

具体的に(SurferOnWww様の表現をお借りして)次のような意味になります。

JavaScript で addEventListener を使ってリスナをアタッチする際、イベントが発生する要素に直接リスナをアタッチした方が良いのか、その要素の親の要素(例えば document)にアタッチしてキャプチャリングとかバブリングで捕捉した方が良いのか?

背景、状況

jQuery は少し書けるのですが、Vanilla JS 化に取り組んでいます。
そこでaddEventListenerの使い方について、どちらがいつ良いのかがわかりません。
広くご意見頂戴できましたら幸いです。

以下にサンプルケースを挙げてみましたが、他に「こういうケースではこっちの方が良いよ」とか「こういうケースではこっちは使いにくいよ」などより具体的に何かございましたらご教示頂きたく存じます。

何卒宜しくお願い申し上げます。

サンプル

その都度書く

JavaScript

1var btn1 = document.getElementById('btn1'); 2btn1.addEventListener('click', function() { 3 console.log('#btn1をクリックしました'); 4}, false); 5 6var btn2 = document.getElementById('btn2'); 7btn2.addEventListener('click', function() { 8 console.log('#btn2をクリックしました'); 9}, false);

中で分岐する

JavaScript

1document.addEventListener('click', function(evt) { 2 if ( evt.target.id === 'btn1' ) { 3 console.log('#btn1をクリックしました'); 4 } else if( evt.target.id === 'btn2' ) { 5 console.log('#btn2をクリックしました'); 6 } 7}, false);

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

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

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

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

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

回答3

#1

退会済みユーザー

退会済みユーザー

総合スコア0

投稿2023/02/11 05:12

編集2023/02/11 05:21

質問を書き直した方が良いのでは? 

JavaScriptの addEventListener はその都度書くべきか?分岐すべきか?

 ↓↓↓

JavaScript で addEventListener を使ってリスナをアタッチする際、イベントが発生する要素に直接リスナをアタッチした方が良いのか、その要素の親の要素(例えば document)にアタッチしてキャプチャリングとかバブリングで捕捉した方が良いのか?

それはもう適材適所としか言えません。


【追記】

後者(親で捕捉)とする場合、伝播は 3 つのフェーズに分かれており、Capturing Phase(捕捉フェーズ)⇒ Target Phase(対象フェーズ)⇒ Bubbling Phase(浮上フェーズ)という順番になります。それぞれのフェーズの説明は以下の通りです。

(1) Capturing Phase では、window ⇒ document ⇒ その中の親 ⇒ 子 ⇒ 孫 ⇒ ひ孫 ・・・といった具合に、親子関係を親側から順にたぐって、イベントが起きたオブジェクトの親まで(「親まで」という点に注意)の各オブジェクトにイベントが送信されていきます。

(2) Target Phase では、イベントの原因となったオブジェクトにイベントが送信されます。

(3) Bubbling Phase では、イベントを発生させたオブジェクトの親から(「親から」という点に注意)順に浮上していき、window に達するまで各オブジェクトに順にイベントが送信されていきます。

・・・と言うことで少々注意が必要と思います。

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

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

#2

Cocode

総合スコア2314

投稿2023/02/11 08:29

私ならこうする程度の意見ですが…。

純粋に提示された例についてお答えすると、私でしたら「都度書く」で対応してしまいます。
ただし共通のclassをつけて.forEach()でリスナーをつけます。

html

1<button id="btn1" class="btn">Button 1</button> 2<button id="btn2" class="btn">Button 2</button>

javascript

1const btns = document.querySelectorAll('.btn'); 2btns.forEach(btn => btn.addEventListener('click', myFunction)); 3 4function myFunction(e) { 5 console.log(`${e.target.id}がクリックされました。`); 6}

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

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

#3

miwakazuo

総合スコア52

投稿2023/02/14 03:28

オブジェクトごとに扱うイベントタイプや処理が異なる場合は、その都度書く方が適していると思います。
例えば動画アプリで再生・停止ボタンや音量スライダーから、クリックイベントやドラッグイベントを取得する場合とかです。

javascript

1playBtn.addEventListener('click', playSound, false); 2pauseBtn.addEventListener('click', pauseSound, false); 3volumeSlider.addEventListener('dragstart', changeVolume, false);

これを分岐する方法で書くと、

javascript

1document.addEventListener('click', event => { 2 if(event.target.id === 'playBtn'){ 3 playSound(); 4 } 5 else if(event.target.id === 'pauseBtn'){ 6 pauseSound(); 7 } 8}, false); 9 10document.addEventListener('dragstart', event => { 11 if(event.target.id === 'volumeSlider'){ 12 changeVolume(); 13 } 14}, false);

という感じで、ちょっと冗長になります。

一方、複数のオブジェクトに対して単一のイベントを扱う場合は、中で分岐する書き方もありかと思います。
例えばパズルゲームやカレンダーなど、同じクラスのインスタンスに対して、どれがクリックされたかを取得したい場合などです。

javascript

1document.getElementId('puzzle').addEventListener('click', event => { 2 if(event.target.classList.contains('piece')){ 3 selectPiece(piece); 4 } 5}, false);

これを「その都度書く」方法で書くとこのようになります。

javascript

1Array.prototype.forEach.call( 2 document.querySelectorAll('#puzzle .piece'), 3 piece => { 4 piece.addEventListener('click', event => { 5 selectPiece(piece); 6 }, false); 7 } 8);

スクリプトの文脈としては、前者は「クリックされたものがピースだったら」で、後者は「ピースをクリックしたら」といった感じですね。

ケースバイケースで良いと思いますが、個人的には多少行数が増えても、文脈的にわかりやすい方を優先した方が、後々自分も他人も解読しやすくなりますので、よろしいかと思います。

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

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

最新の回答から1ヶ月経過したため この意見交換はクローズされました

意見をやりとりしたい話題がある場合は質問してみましょう!

質問する

関連した質問