クラスのJavaScriptクリックイベントリスナー


220

現在、JavaScriptを記述して、クリックされたクラスの属性を取得しようとしています。これを正しく行うには、イベントリスナーを使用する必要があることを知っています。私のコードは次のとおりです:

var classname = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

classname.addEventListener('click', myFunction(), false);

属性をクリックしてクラスの1つをクリックするたびに警告ボックスが表示されることを期待していましたが、残念ながらこれは機能しません。誰か助けてくれますか?

- これは非常に簡単に実行できますjQueryが、使用したくありません


2
イベントリスナーを追加するコードに問題があります。addEventListenerは、イベント名( 'クリック')、関数への参照(現在は括弧でmyFunction()を呼び出すことによる関数の結果ではありません)、およびイベントのバブリングを示すフラグを取ります。addEventListener呼び出しはelem.addEventListener( 'click'、myFunction、false)のようになり、クラス名はNodeListタイプです。すべての要素をループし、リストの各要素にリスナーをアタッチする必要があります。
ジョーイゲラ2015年

回答:


373

これは動作するはずです。基準に一致する要素の配列のような配列オブジェクト(編集を参照)をgetElementsByClassName返します。

var elements = document.getElementsByClassName("classname");

var myFunction = function() {
    var attribute = this.getAttribute("data-myattribute");
    alert(attribute);
};

for (var i = 0; i < elements.length; i++) {
    elements[i].addEventListener('click', myFunction, false);
}

jQueryはループ処理を実行します。これはプレーンなJavaScriptで実行する必要があります。

あなたが持っている場合はES6をサポートし、あなたとあなたの最後の行を置き換えることができます。

    Array.from(elements).forEach(function(element) {
      element.addEventListener('click', myFunction);
    });

注:古いブラウザ(IE6、IE7、IE8など)はサポートgetElementsByClassNameしていないため、を返しundefinedます。


編集:修正

getElementsByClassNameは配列を返しませんが、ほとんどの場合HTMLCollectionを返し、一部のブラウザーではNodeListを返します(Mozilla ref)。これらのタイプは両方とも配列のように(それらには長さプロパティがあり、オブジェクトはそれらのインデックスを介してアクセスできます)、厳密には配列または配列から継承されません。(配列で実行できる他のメソッドは、これらのタイプでは実行できません)

これを指摘し、完全に理解するために掘り下げてくれたユーザー@ Nemoに感謝します。


6
これは完全に機能します。ありがとうございました。jQueryがループを実行していることに実際には気付きませんでした。Anudeepを大いに助けてください。これがあなたの実際の答えです:jsfiddle.net/LWda3/2
30secondstosam

2
document.getElementsByClassName基準に一致する要素が1つだけであっても、実際には常に配列を返します
Guilherme Sehn

ただし、配列の最初の要素はすべてのdom要素です。したがって、forループは1から開始します
Vishal Sakaria

11
stackoverflow.com/a/13258908/1333493「document.getElementsByClassNameは配列を返しません。XMLファイルのようにたどられるノードリストを返します。」
Nemo

9
Array.from()マップ関数である2番目のパラメーターがあるため、上記(es6サポートを想定)を記述できますArray.from(classname, c => c.addEventListener('click', myFunction));
キルマイジング

12

*これは、ターゲットクラスの子がイベントをトリガーできるように編集されました。詳細については、回答の下部を参照してください。*

アイテムが頻繁に追加および削除されるクラスにイベントリスナーを追加するための代替回答。これはon、イベントがリッスンしている子要素のセレクターを渡すことができるjQueryの関数に触発されています。

var base = document.querySelector('#base'); // the container for the variable content
var selector = '.card'; // any css selector for children

base.addEventListener('click', function(event) {
  // find the closest parent of the event target that
  // matches the selector
  var closest = event.target.closest(selector);
  if (closest && base.contains(closest)) {
    // handle class event
  }
});

フィドル:https : //jsfiddle.net/u6oje7af/94/

これはbase要素の子のクリックをリッスンし、クリックのターゲットにセレクターと一致する親がある場合、クラスイベントが処理されます。個々の要素にクリックリスナーを追加することなく、必要に応じて要素を追加および削除できます。これは、jQuery機能と同様に、このリスナーが追加された後に追加された要素であっても、それらすべてをキャッチします(内部的には多少似ていると思います)。

これは、伝播するイベントに依存するため、stopPropagation他の場所でイベントに参加している場合、これは機能しない可能性があります。また、このclosest関数にはIEとの互換性の問題があるようです(そうでないことは?)。

このタイプのアクションを繰り返し聞く必要がある場合は、これを関数にすることができます。

function addChildEventListener(base, eventName, selector, handler) {
  base.addEventListener(eventName, function(event) {
    var closest = event.target.closest(selector);
    if (closest && base.contains(closest)) {
      // passes the event to the handler and sets `this`
      // in the handler as the closest parent matching the
      // selector from the target element of the event
      handler.call(closest, event);
    }
  });
}

=========================================
編集:この投稿はもともとmatches関数を使用しましたイベントターゲットのDOM要素。ただし、これにより、イベントのターゲットが直接クラスのみに制限されました。closest代わりに関数を使用するように更新され、目的のクラスの子のイベントでもイベントをトリガーできるようになりました。元のmatchesコードは元のフィドルで見つけることができます:https : //jsfiddle.net/u6oje7af/23/


3

以下のコードを使用できます。

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);

私はこれを試してみる必要があります、それはループよりも実際に維持とパフォーマンスがより簡単かもしれないユニークなアプローチです!
クリフヘルセル

4
要素に複数のクラスがある場合、そのフィールドの正しい値を確認する必要があります。クラスと順序。私はむしろ行きたいevt.target.classList.contains('databox')
honk31

8
これは私には非常に効率が悪いようです。身体のすべてのイベントがこの関数を通過します。ループについて維持するのが難しいのは何ですか?
JosefAssad

これは非常に非効率的です。@ JosefAssadが言ったように、各要素を調べます。
nullwriter

3

最新のJavaScriptでは、次のように実行できます。

const divs = document.querySelectorAll('.a');

divs.forEach(el => el.addEventListener('click', event => {
  console.log(event.target.classList[1]);
}));
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Example</title>
  <style>
    .a {
      background-color:red;
      height: 33px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
      cursor: pointer;
    }
    
    .b {
      background-color:#00AA00;
      height: 50px;
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
  </style>
</head>
<body>
  <div class="a a-1">1</div>
  <div class="b">2</div>
  <div class="a a-2">11</div>
</body>
</html>

  1. クラス名ですべての要素を取得します
  2. forEachを使用してすべての要素をループします
  3. 各要素にイベントリスナーをアタッチする
  4. event.target特定の要素の詳細情報を取得するために使用します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.