Elemente nach Attribut abrufen, wenn querySelectorAll ohne Verwendung von Bibliotheken nicht verfügbar ist?


123
<p data-foo="bar">

Wie können Sie das Äquivalent zu tun

document.querySelectorAll('[data-foo]')

wo querySelectorAll ist nicht verfügbar ?

Ich brauche eine native Lösung, die zumindest in IE7 funktioniert. IE6 ist mir egal.


Überprüfen Sie die aus sizzle.js Javascript Selektor Bibliothek
— Epoche

1
Schön, ja, die einzige Auswahl, die ich treffen muss, sind Datenattribute, also habe ich versucht, den einfachsten Weg zu finden, um das zu patchen, ohne eine ganze Selektor-Engine wie Sizzle zu ziehen. Aber guter Punkt, um in die Quelle zu schauen. Übrigens ist eine weitere großartige
— Auswahlmaschine

@ryanve, danke, ich werde einen Blick darauf werfen :)
— Epoche

Die Arbeitslösung, die ich verwendet habe, ist in github.com/ryanve/dope/blob/master/dope.js in der Methode 'queryAttr'
— ryanve

7
Lol, deine Frage ist meine Antwort. Das kommt also mit einer anderen Frage. In welcher Situation querySelectorAllist das nicht verfügbar? note - I don't care all IE
— Vzhen

Antworten:


136

Sie können eine Funktion schreiben, die getElementsByTagName ('*') ausführt und nur die Elemente mit dem Attribut "data-foo" zurückgibt:

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++)
  {
    if (allElements[i].getAttribute(attribute) !== null)
    {
      // Element exists with attribute. Add to array.
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

Dann,

getAllElementsWithAttribute('data-foo');

8
Die Verwendung != nullist der ideale Weg (besser als mein Kommentar oben), da getAttribute im alten IE einen Wert zurückgeben kann, dessen typeofis'number'
— ryanve

1
Warum verwenden document.getElementsByTagName('*')statt document.all?
— Pedrozath

1
Warum nicht hasAttributelieber verwenden als getAttribute() !== null, da Sie nur die Existenz und nicht ihren Wert überprüfen möchten?
— Rvighne

61

Verwenden

//find first element with "someAttr" attribute
document.querySelector('[someAttr]')

oder

//find all elements with "someAttr" attribute
document.querySelectorAll('[someAttr]') 

Elemente nach Attributen zu finden. Es wird jetzt in allen relevanten Browsern (sogar IE8) unterstützt: http://caniuse.com/#search=queryselector


2
Wie hat dies so viele positive Stimmen, wenn die Frage explizit fragt: "Ich brauche eine native Lösung , die zumindest in IE7 funktioniert ". Zweitens besagt dieser Link, dass die Unterstützung in IE11 beginnt, obwohl sie tatsächlich in IE8 beginnt. Vielleicht sollte diese auf developer.mozilla.org/en-US/docs/Web/API/Element/… ausgetauscht werden, damit die Antwort tatsächlich unterstützt wird. ..?
— Zze

7
Der Grund für all die Upvotes und der Grund, warum ich die Antwort gegeben habe, ist, dass diese SO-Frage wirklich alt ist. Wenn Sie also nach DOM-Elementen suchen, finden Sie diese Frage in den Suchergebnissen sehr hoch, und da es sich um Personen handelt suchen sie upvote. Nützlichkeit> historische Genauigkeit. Zweitens funktioniert der Link immer noch einwandfrei. Caniuse.com hat nur alte Browser ausgeblendet. Wenn Sie zu "Usage relative" wechseln, werden die alten Browser weiterhin angezeigt.
— Pylinux

Hat perfekt funktioniert. Schnell und einfach
— Dawson B

Es ist 2020. Dies sollte jetzt die akzeptierte Antwort sein.
— NearHuscarl

44

Ich habe ein bisschen herumgespielt und bin zu dieser groben Lösung gekommen:

function getElementsByAttribute(attribute, context) {
  var nodeList = (context || document).getElementsByTagName('*');
  var nodeArray = [];
  var iterator = 0;
  var node = null;

  while (node = nodeList[iterator++]) {
    if (node.hasAttribute(attribute)) nodeArray.push(node);
  }

  return nodeArray;
}

Die Verwendung ist recht einfach und funktioniert sogar in IE8:

getElementsByAttribute('data-foo');
// or with parentNode
getElementsByAttribute('data-foo', document);

http://fiddle.jshell.net/9xaxf6jr/

Ich empfehle jedoch, querySelector/ Alldafür zu verwenden (und um ältere Browser zu unterstützen, verwenden Sie eine Polyfüllung ):

document.querySelectorAll('[data-foo]');

Ja, +1 für querySelectorAll. Ein schneller jsperf-Test jsperf.com/custom-vs-selectorall-attributes zeigt, dass es viel schneller ist als die akzeptierte Antwort ... leider ist es nicht IE 7-kompatibel :(
— Sebastien Daniel

11

Versuchen Sie dies, es funktioniert

document.querySelector ('[attribute = "value"]')

Beispiel:

document.querySelector('[role="button"]')

5

Das funktioniert auch:

document.querySelector([attribute="value"]);

So:

document.querySelector([data-foo="bar"]);

2
Hier fehlen die einfachen Anführungszeichen im eigentlichen querySelector. Sollte sein: document.querySelector('[data-foo="bar"]');
— Brettins

1

Versuchen Sie dies - ich habe die obigen Antworten leicht geändert:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

Dann,

getAttributes('data-foo');

3
Was hast du geändert und warum?
— Artjom B.

1

Eine kleine Änderung an der Antwort von @kevinfahy , damit das Attribut bei Bedarf nach Wert abgerufen werden kann:

function getElementsByAttributeValue(attribute, value){
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].getAttribute(attribute) !== null) {
      if (!value || allElements[i].getAttribute(attribute) == value)
        matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

0

Nicht im Browser verwenden

Verwenden Sie im Browser document.querySelect('[attribute-name]').

Wenn Sie jedoch Unit-Tests durchführen und Ihr verspotteter Dom über eine Flakey-QuerySelector-Implementierung verfügt, reicht dies aus.

Dies ist die Antwort von @ kevinfahy, die nur auf ES6-Fettpfeilfunktionen reduziert wurde und die HtmlCollection möglicherweise auf Kosten der Lesbarkeit in ein Array konvertiert.

Es funktioniert also nur mit einem ES6-Transpiler. Ich bin mir auch nicht sicher, wie performant es mit vielen Elementen sein wird.

function getElementsWithAttribute(attribute) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) !== null);
}

Und hier ist eine Variante, die ein Attribut mit einem bestimmten Wert erhält

function getElementsWithAttributeValue(attribute, value) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) === value);
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.