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.