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 mitTreeWalkerund Abfragen mit XPath. TreeWalkerist die vielseitigste native Option für vollständige DOM-Textsuchen über beliebige Elementtypen hinweg, ohne vorab eine große NodeList zu erstellen.- Bevorzugen Sie
textContentgegenüberinnerTextfü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_SKIPvs.FILTER_REJECT: Die Verwendung vonFILTER_SKIPbedeutet hier, dass der Walker weiterhin in die Kindelemente eines nicht übereinstimmenden Knotens absteigt. Wenn Sie stattdessenFILTER_REJECTverwenden würden, würde der Walker den Knoten und seinen gesamten Teilbaum überspringen. Für Textsuchen istFILTER_SKIPfast immer die richtige Wahl, da dertextContenteines Elternelements möglicherweise nicht übereinstimmt, obwohl der eines tieferen Nachfahren es tut.
Discover how at OpenReplay.com.
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:
| Eigenschaft | Gibt zurück | Löst Layout aus? |
|---|---|---|
textContent | Roher DOM-Text, einschließlich versteckter Elemente | Nein |
innerText | Nur gerenderter Text | Ja (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-Suche →
TreeWalker - 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.