Eine Reihe von Optionen zum Durchlaufen von querySelectorAll NodeLists

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ein häufiges Bedürfnis beim Schreiben von Vanilla JavaScript ist das Finden einer Auswahl von Elementen im DOM und das Durchlaufen dieser Elemente. Zum Beispiel das Finden von Instanzen eines Buttons und das Anhängen eines Klick-Handlers.

const buttons = document.querySelectorAll(".js-do-thing");
// There could be any number of these! 
// I need to loop over them and attach a click handler.

Es gibt SO VIELE Möglichkeiten, dies zu tun. Lassen Sie uns sie durchgehen.

forEach

forEach ist normalerweise für Arrays, und interessanterweise ist das, was von querySelectorAll zurückkommt, kein Array, sondern eine NodeList. Glücklicherweise unterstützen die meisten modernen Browser die Verwendung von forEach auf NodeLists ohnehin.

buttons.forEach((button) => {
  button.addEventListener('click', () => {
    console.log("forEach worked");
  });
});

Wenn Sie sich Sorgen machen, dass forEach möglicherweise nicht auf Ihrer NodeList funktioniert, könnten Sie sie zuerst in ein Array "spreaden"

[...buttons].forEach((button) => {
  button.addEventListener('click', () => {
    console.log("spread forEach worked");
  });
});

Aber ich bin mir nicht sicher, ob das etwas nützt, da es unwahrscheinlich ist, dass es Browser gibt, die Spreads unterstützen, aber nicht forEach auf NodeLists. Vielleicht wird es seltsam, wenn Transpilation ins Spiel kommt, aber ich weiß es nicht. So oder so, Spreading ist nett, falls Sie etwas anderes Array-spezifisches verwenden möchten, wie .map(), .filter() oder .reduce().

Eine etwas ältere Methode ist, sich mit diesem kleinen Hack in das natürliche forEach des Arrays einzuklinken

[].forEach.call(buttons, (button) => {
  button.addEventListener('click', () => {
    console.log("array forEach worked");
  });
});

Todd Motto hat diese Methode allerdings einmal stark kritisiert, also seien Sie gewarnt. Er empfahl, Ihre eigene Methode zu entwickeln (aktualisiert für ES6)

const forEach = (array, callback, scope) => {
  for (var i = 0; i < array.length; i++) {
    callback.call(scope, i, array[i]); 
  }
};

...die wir so verwenden würden

forEach(buttons, (index, button) => {
  console.log("our own function worked");
});

for .. of

Die Browserunterstützung für for .. of Schleifen sieht ziemlich gut aus und das scheint mir eine super saubere Syntax zu sein

for (const button of buttons) {
  button.addEventListener('click', () => {
    console.log("for .. of worked");
  });
}

Sofort ein Array erstellen

const buttons = Array.prototype.slice.apply(
  document.querySelectorAll(".js-do-thing")
);

Jetzt können Sie alle normalen Array-Funktionen verwenden.

buttons.forEach((button) => {
  console.log("apply worked");
});

Alte for-Schleife

Wenn Sie maximale Browserkompatibilität benötigen, ist es keine Schande, eine uralte klassische for-Schleife zu verwenden

for (let i = 0; i < buttons.length; ++i) {
  buttons[i].addEventListener('click', () => {
    console.log("for loop worked");
  });
}

Moment! Das obige Beispiel enthält Pfeilfunktionen und ES6 let. Wenn Sie ältere Versionen unterstützen möchten und altes IE und ähnliches, müssen Sie...

for (var i = 0; i < buttons.length; ++i) {
  buttons[i].addEventListener('click', function() {
    console.log("for loop worked");
  });
}

Bibliotheken

Wenn Sie jQuery verwenden, müssen Sie sich nicht einmal darum kümmern...

$(".buttons").on("click", () => {
  console.log("jQuery works");
});

Wenn Sie ein React/JSX-Setup verwenden, müssen Sie sich überhaupt keine Gedanken über diese Art von Binding machen.

Lodash hat auch ein _.forEach, das vermutlich bei älteren Browsern hilft.

_.forEach(buttons, (button, key) => {
  console.log("lodash worked");
});

Umfrage

Twitter-Leute

Außerdem gibt es hier ein Pen mit all diesen Optionen.