JavaScript-Klickereignis-Listener für die Klasse

220

Ich versuche gerade, JavaScript zu schreiben, um das Attribut der Klasse zu erhalten, auf die geklickt wurde. Ich weiß, dass ich einen Ereignis-Listener verwenden sollte, um dies richtig zu machen. Mein Code lautet wie folgt:

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

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

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

Ich hatte erwartet, jedes Mal eine Warnmeldung zu erhalten, wenn ich auf eine der Klassen klickte, um mir das Attribut mitzuteilen, aber leider funktioniert dies nicht. Kann mir bitte jemand helfen?

( Hinweis - Ich kann dies ganz einfach tun jQuery, möchte es aber NICHT verwenden. )

30 Sekunden Stosam
quelle
2
Es gibt ein Problem mit dem Code, der den Ereignis-Listener hinzufügt. addEventListener verwendet den Ereignisnamen ('click'), einen Verweis auf die Funktion (nicht das Ergebnis der Funktion, wie sie jetzt durch Aufrufen von myFunction () mit parens ist) und ein Flag, um das Sprudeln von Ereignissen anzuzeigen. Der Aufruf von addEventListener sollte folgendermaßen aussehen: elem.addEventListener ('click', myFunction, false) und classname ist ein NodeList-Typ. Sie müssen alle Elemente durchlaufen und den Listener an jedes Element in der Liste anhängen.
Joey Guerra

Antworten:

373

Das sollte funktionieren. getElementsByClassNameGibt ein Array zurück. Array-ähnliches Objekt (siehe Bearbeiten) der Elemente, die den Kriterien entsprechen.

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 erledigt den Loop-Teil für Sie, den Sie in einfachem JavaScript ausführen müssen.

Wenn Sie ES6-Unterstützung haben , können Sie Ihre letzte Zeile durch Folgendes ersetzen:

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

Hinweis: Ältere Browser (wie IE6, IE7, IE8) werden nicht unterstützt getElementsByClassNameund kehren daher zurück undefined.


EDIT: Korrektur

getElementsByClassNamegibt kein Array zurück, aber in den meisten Fällen eine HTMLCollection oder in einigen Browsern eine NodeList ( Mozilla ref ). Beide Typen sind Array-ähnlich (dh sie haben eine Längeneigenschaft und auf die Objekte kann über ihren Index zugegriffen werden), sind jedoch nicht ausschließlich ein Array oder werden von einem Array geerbt. (Dies bedeutet, dass andere Methoden, die für ein Array ausgeführt werden können, für diese Typen nicht ausgeführt werden können.)

Vielen Dank an user @ Nemo, der darauf hingewiesen und mich dazu gebracht hat, alles zu verstehen.

Anudeep Bulla
quelle
6
Das funktioniert perfekt. Danke dir. Ich wusste eigentlich nicht, dass jQuery die Schleife gemacht hat. Große Hilfe Anudeep. Hier ist Ihre Arbeitsantwort: jsfiddle.net/LWda3/2
30secondstosam
2
document.getElementsByClassNameTatsächlich wird immer ein Array zurückgegeben, auch wenn nur ein Element den Kriterien entspricht
Guilherme Sehn
Vorsicht, obwohl das erste Element des Arrays alle dom-Elemente sind. Beginnen Sie also Ihre for-Schleife mit 1
Vishal Sakaria
11
stackoverflow.com/a/13258908/1333493 "document.getElementsByClassName gibt kein Array zurück. Es gibt eine Knotenliste zurück, die wie eine XML-Datei durchlaufen wird."
Nemo
9
Array.from()hat einen zweiten Parameter, der eine Kartenfunktion ist, so dass der obige (unter der Annahme, dass es6 unterstützt wird) geschrieben werden kann Array.from(classname, c => c.addEventListener('click', myFunction));.
Kilmazing
12

* Dies wurde bearbeitet, damit Kinder der Zielklasse die Ereignisse auslösen können. Einzelheiten finden Sie unten in der Antwort. * *

Eine alternative Antwort zum Hinzufügen eines Ereignis-Listeners zu einer Klasse, in der häufig Elemente hinzugefügt und entfernt werden. Dies ist inspiriert von der onFunktion von jQuery, mit der Sie einen Selektor für ein untergeordnetes Element übergeben können, das das Ereignis abhört.

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
  }
});

Geige: https://jsfiddle.net/u6oje7af/94/

Dadurch wird auf Klicks auf untergeordnete baseElemente des Elements gewartet. Wenn für das Ziel eines Klicks ein übergeordnetes Element mit dem Selektor übereinstimmt, wird das Klassenereignis behandelt. Sie können Elemente beliebig hinzufügen und entfernen, ohne den einzelnen Elementen weitere Klick-Listener hinzufügen zu müssen. Dies wird sie alle auch für Elemente erfassen, die nach dem Hinzufügen dieses Listeners hinzugefügt wurden, genau wie die jQuery-Funktionalität (die ich mir unter der Haube etwas ähnlich vorstelle).

Dies hängt von den sich ausbreitenden Ereignissen ab. Wenn Sie sich also stopPropagationan einem anderen Ort befinden, funktioniert dies möglicherweise nicht. Außerdem hat die closestFunktion anscheinend einige Kompatibilitätsprobleme mit dem IE (was nicht?).

Dies könnte zu einer Funktion gemacht werden, wenn Sie diese Art von Aktion wiederholt abhören müssen, wie z

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);
    }
  });
}

========================================= BEARBEITEN
: Dieser Beitrag verwendete ursprünglich die matchesFunktion für DOM-Elemente auf dem Ereignisziel, dies beschränkte die Ziele von Ereignissen jedoch nur auf die direkte Klasse. Es wurde aktualisiert, um closeststattdessen die Funktion zu verwenden, sodass Ereignisse für untergeordnete Elemente der gewünschten Klasse auch die Ereignisse auslösen können. Der Originalcode matchesbefindet sich in der Originalgeige: https://jsfiddle.net/u6oje7af/23/

obermillerk
quelle
3

Sie können den folgenden Code verwenden:

document.body.addEventListener('click', function (evt) {
    if (evt.target.className === 'databox') {
        alert(this)
    }
}, false);
Rajat Kumar
quelle
Ich muss es versuchen, es ist ein einzigartiger Ansatz, der möglicherweise einfacher zu warten und eine bessere Leistung zu erzielen ist als eine Schleife!
Cliff Helsel
4
Wenn das Element mehrere Klassen hat, müssten Sie in diesen Feldern nach dem richtigen Wert suchen, z. Klassen und Ordnung. Ich würde lieber gehen fürevt.target.classList.contains('databox')
Honk31
8
Das scheint mir äußerst ineffizient zu sein. Jedes einzelne Ereignis am Körper würde diese Funktion durchlaufen. Was ist an einer Schleife so schwer zu pflegen?
JosefAssad
Dies ist sehr ineffizient. Sie würden jedes Element durchgehen, wie @JosefAssad sagte.
Nullwriter
3

Mit modernem JavaScript geht das folgendermaßen:

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. Ruft alle Elemente nach Klassennamen ab
  2. Schleift alle Elemente mit forEach
  3. Fügen Sie jedem Element einen Ereignis-Listener hinzu
  4. Dient event.targetzum Abrufen weiterer Informationen für ein bestimmtes Element
V. Sambor
quelle