Back

So finden Sie DOM-Elemente nach Text

So finden Sie DOM-Elemente nach Text

Es gibt keine getElementByText()-Methode in der DOM-API. Wenn Sie ein Element anhand seines Inhalts und nicht anhand seiner Struktur lokalisieren müssen, müssen Sie diese Funktionalität selbst implementieren. Dies kommt häufiger vor, als man denkt – bei Automatisierungsskripten, UI-Tests, dynamischem Content-Parsing – und der richtige Ansatz hängt davon ab, wie viel Flexibilität Sie benötigen.

Wichtigste Erkenntnisse

  • Die DOM-API bietet keine integrierte Methode zur Auswahl von Elementen nach Textinhalt, aber drei native Ansätze schließen diese Lücke: Filtern mit querySelectorAll, Traversieren mit TreeWalker und Abfragen mit XPath.
  • TreeWalker ist die vielseitigste native Option für vollständige DOM-Textsuchen über beliebige Elementtypen hinweg, ohne vorab eine große NodeList zu erstellen.
  • Bevorzugen Sie textContent gegenüber innerText für Textabgleiche – es ist schneller, vermeidet das Auslösen von Layout-Neuberechnungen und verhält sich konsistent unabhängig von der Sichtbarkeit des Elements.
  • Achten Sie auf häufige Fallstricke wie zusätzliche Leerzeichen, verschachtelten Nachfahrentext und dynamisch eingefügten Content, der möglicherweise nicht vorhanden ist, wenn Ihr Skript ausgeführt wird.

Warum querySelector nicht nach DOM-Textinhalt abfragen kann

querySelector() und querySelectorAll() akzeptieren nur CSS-Selektoren. Obwohl CSS eine :has()-Pseudoklasse und Attributselektoren bietet, gibt es keinen Standard-CSS-Selektor zum Abgleichen des Textinhalts eines Elements. Selektoren wie div:text("Submit") existieren in der Spezifikation schlichtweg nicht.

Das lässt Ihnen drei praktische Ansätze: Filtern einer Kandidatenmenge, Traversieren des DOM mit einer nativen API oder Verwendung von XPath.

Methode 1: Filtern einer Kandidatenmenge nach Text

Der einfachste Ansatz besteht darin, Elemente nach Tag oder Klasse abzufragen und dann nach Text zu filtern. Dies funktioniert gut, wenn Sie den Elementtyp im Voraus kennen.

function findByText(tag, text) {
  return [...document.querySelectorAll(tag)].filter(el =>
    el.textContent.trim() === text
  )
}

// Verwendung
const buttons = findByText('button', 'Submit')

Dies ist lesbar und schnell, wenn die Kandidatenmenge klein ist. Die Schwäche: Es durchsucht jeweils nur einen Elementtyp. Die Suche nach allen Elementen mit '*' funktioniert, ist aber bei großen DOMs langsamer.

Methode 2: Traversieren des DOM mit TreeWalker

TreeWalker ist eine integrierte DOM-API, mit der Sie effizient durch Knoten navigieren können. Sie wird in allen modernen Browsern gut unterstützt und vermeidet den Overhead, vorab eine vollständige NodeList zu erstellen.

function findElementsByText(root, text) {
  const walker = document.createTreeWalker(
    root,
    NodeFilter.SHOW_ELEMENT,
    {
      acceptNode(node) {
        return node.textContent.trim() === text
          ? NodeFilter.FILTER_ACCEPT
          : NodeFilter.FILTER_SKIP
      }
    }
  )

  const results = []
  while (walker.nextNode()) results.push(walker.currentNode)
  return results
}

// Verwendung
const matches = findElementsByText(document.body, 'TV')

Dies durchsucht jeden Elementtyp im gesamten Baum – eine generische Lösung, die der tag-spezifische Ansatz nicht bieten kann. Es unterstützt auch einen vorzeitigen Abbruch, wenn Sie nur das erste Ergebnis benötigen.

Hinweis zu FILTER_SKIP vs. FILTER_REJECT: Die Verwendung von FILTER_SKIP bedeutet hier, dass der Walker weiterhin in die Kindelemente eines nicht übereinstimmenden Knotens absteigt. Wenn Sie stattdessen FILTER_REJECT verwenden würden, würde der Walker den Knoten und seinen gesamten Teilbaum überspringen. Für Textsuchen ist FILTER_SKIP fast immer die richtige Wahl, da der textContent eines Elternelements möglicherweise nicht übereinstimmt, obwohl der eines tieferen Nachfahren es tut.

Methode 3: XPath-Textsuche im DOM

Für ausdrucksstärkere Abgleiche unterstützt document.evaluate() XPath-Ausdrücke, einschließlich textbasierter Abfragen. Dies ist die leistungsfähigste Option für komplexe Muster.

function findByXPath(expression, context = document) {
  const result = document.evaluate(
    expression,
    context,
    null,
    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
    null
  )

  return Array.from({ length: result.snapshotLength }, (_, i) =>
    result.snapshotItem(i)
  )
}

// Findet jedes Element, das den Text "Submit" enthält
const els = findByXPath('//*[contains(text(), "Submit")]')

Die XPath-Textsuche im DOM behandelt partielle Übereinstimmungen und komplexe Bedingungen elegant. Der Kompromiss ist die Lesbarkeit – die XPath-Syntax ist den meisten Frontend-Entwicklern nicht vertraut.

Eine Sache, die Sie beachten sollten: contains(text(), "Submit") gleicht nur die direkten Textknoten des Elements ab. Wenn „Submit” in einem Kindelement enthalten ist, wird dieser Ausdruck das Elternelement nicht treffen. Um über alle Nachfahrentexte hinweg zu suchen, verwenden Sie stattdessen contains(., "Submit"), wobei . sich auf den String-Wert des gesamten Elements einschließlich seiner Nachfahren bezieht.

textContent vs. innerText: Was für den Abgleich verwenden?

Beide Eigenschaften geben Text zurück, verhalten sich aber unterschiedlich:

EigenschaftGibt zurückLöst Layout aus?
textContentRoher DOM-Text, einschließlich versteckter ElementeNein
innerTextNur gerenderter TextJa (Reflow)

Verwenden Sie textContent für Textabgleiche. Es ist schneller, löst keine Layout-Neuberechnung aus und funktioniert konsistent über alle Elemente hinweg, unabhängig von der Sichtbarkeit.

Häufige Fallstricke beim Finden von DOM-Elementen nach Text

Leerzeichen: textContent enthält Leerzeichen aus der HTML-Formatierung. Verwenden Sie immer .trim() vor dem Vergleich.

Verschachtelter Text: Der textContent eines Elements umfasst den gesamten Nachfahrentext. <div><span>TV</span></div> – der textContent des div ist ebenfalls "TV". Seien Sie spezifisch darüber, welche Elementebene Sie ansprechen.

Dynamischer Content: Nach dem Seitenladen eingefügter Text ist nicht vorhanden, wenn Ihr Skript ausgeführt wird. Verwenden Sie einen MutationObserver oder führen Sie Ihre Suche aus, nachdem bestätigt wurde, dass der Content existiert.

Den richtigen Ansatz wählen

  • Bekannter Elementtyp, einfacher Abgleich → Filtern mit querySelectorAll
  • Beliebiger Elementtyp, vollständige DOM-SucheTreeWalker
  • Partielle Übereinstimmung oder komplexes Muster → XPath über document.evaluate()

Wenn Sie in einem Testkontext arbeiten, bieten Tools wie Testing Library getByText() integriert an – gut zu wissen, obwohl die oben genannten nativen Techniken für Nicht-Test-Skripte weiterhin unverzichtbar bleiben.

Fazit

Die textbasierte DOM-Suche ist eine Lücke in der Standard-API, aber diese drei Ansätze decken jeden praktischen Fall ab. Verwenden Sie querySelectorAll mit einem Filter für schnelle, gezielte Suchen, wenn Sie den Elementtyp kennen. Greifen Sie zu TreeWalker, wenn Sie eine vollständige DOM-Traversierung benötigen, ohne sich auf ein bestimmtes Tag festzulegen. Wenden Sie sich an XPath, wenn die Abgleichlogik partiellen Text oder komplexe Bedingungen erfordert. Welche Methode Sie auch wählen, bevorzugen Sie textContent gegenüber innerText, trimmen Sie Leerzeichen vor dem Vergleich und berücksichtigen Sie verschachtelten Nachfahrentext, um falsche Treffer zu vermeiden.

FAQs

Nein. querySelector und querySelectorAll akzeptieren nur CSS-Selektoren, und CSS hat keinen Selektor zum Abgleichen von Textinhalten. Sie müssen JavaScript-basierte Ansätze verwenden, wie das Filtern eines querySelectorAll-Ergebnissatzes, das Durchlaufen des DOM mit TreeWalker oder das Ausführen eines XPath-Ausdrucks mit document.evaluate, um Elemente nach ihrem Inhalt zu lokalisieren.

FILTER_SKIP weist den TreeWalker an, den aktuellen Knoten zu überspringen, aber dennoch seine Kinder zu besuchen. FILTER_REJECT überspringt den Knoten und seinen gesamten Teilbaum. Für textbasierte Suchen ist FILTER_SKIP normalerweise die richtige Wahl, da ein Elternelement möglicherweise nicht übereinstimmt, während ein tieferer Nachfahre es tut.

Nein. Der Ausdruck contains(text(), value) prüft nur die direkten Textknoten des Elements. Wenn die Zielzeichenfolge in einem verschachtelten Kindelement enthalten ist, verwenden Sie stattdessen contains(., value). Der Punkt-Operator bezieht sich auf den vollständigen String-Wert des Elements, einschließlich aller Nachfahrentexte.

textContent ist schneller, weil es keinen Layout-Reflow auslöst. Es gibt den gesamten Text im DOM-Teilbaum zurück, unabhängig von der CSS-Sichtbarkeit, was es konsistent und vorhersehbar macht. innerText gibt nur gerenderten Text zurück und zwingt den Browser, das Layout neu zu berechnen, was unnötigen Overhead für Abgleichzwecke hinzufügt.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay