jQuery / Selector / :has() - Elemente mit passenden Nachfahren auswählen
jQuerys :has(selector) wählt Elemente, die mindestens einen passenden Nachfahren enthalten. $("#menu > li:has(a)") liefert li-Elemente mit Links, nicht die inneren a-Elemente. Nachfahren umfassen direkte Kinder und tiefere Verschachtelungen; für unmittelbare Kinder müssen Sie die Bedingung entsprechend begrenzen.
Enthaltendes und enthaltenes Element
Die :has()-Dokumentation beschreibt das Beibehalten von Kandidaten mit passenden Nachfahren. Ein Link innerhalb eines span bleibt Nachfahre seines li und erfüllt li:has(a). Eine Klasse namens has-link allein genügt nicht; tatsächlich muss ein a enthalten sein.
| Ausdruck | Geprüfte Bedingung | Ergebnis |
|---|---|---|
| li:has(a) | a irgendwo innerhalb | Passende äußere li |
| li:has(> a) | a ist unmittelbares Kind | Passende äußere li |
| li wählen, dann .has("a") | Ausgewählte li enthalten a-Nachfahren | Teilmenge der ursprünglichen li |
| li wählen, dann .find("a") | a innerhalb der li suchen | Innere a-Elemente |
> kennzeichnet die direkte Kindbeziehung. Außen bestimmt #menu > li die Kandidaten, innen legt > a die Beziehung fest, die jedes Element erfüllen muss. Lesen Sie diese Rollen getrennt, um auch verschachtelte Strukturen gezielt auszuwählen.
Vollständiges Beispiel mit Link-Markierungen
Speichern Sie den gesamten Code als UTF-8 in has-demo.html und öffnen Sie ihn im Browser. Eine Paketinstallation ist unnötig; für die offizielle jQuery-Datei vom Content Delivery Network (CDN) benötigen Sie Internetzugang. Das Beispiel verwendet 4.0.0; dasselbe Verhalten wurde mit 3.7.1 und 4.0.0 ausgeführt und geprüft.
plain besitzt keinen Link, direct ein unmittelbares a-Kind und nested einen Link im span. self besitzt lediglich die Klasse has-link. Die Schaltflächen vergleichen Auswahlbedingungen und eine Dokumentänderung.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Items that contain links</title>
<style>
body { font: 16px/1.6 sans-serif; margin: 24px; }
#menu { list-style: none; padding: 0; max-width: 600px; }
#menu > li { border: 2px solid #ddd; margin: 8px 0; padding: 12px; }
#menu > li.marked { border-color: #c45f00; background: #fff5e7; }
button { margin: 4px; padding: 8px; }
</style>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
<h1>Items that contain links</h1>
<ul id="menu">
<li id="plain">No link</li>
<li id="direct"><a id="link-1" href="#example">Direct link</a></li>
<li id="nested"><span><a id="link-2" href="#example">Nested link</a></span></li>
<li id="self" class="has-link">Class name only</li>
</ul>
<button type="button" id="descendants">Any descendant link</button>
<button type="button" id="children">Direct child link</button>
<button type="button" id="add">Add a link to plain</button>
<button type="button" id="reset">Reset</button>
<p id="result" aria-live="polite"></p>
<script>
$(function () {
function show($chosen) {
$("#menu > li").removeClass("marked");
$chosen.addClass("marked");
const ids = $chosen.map((_, item) => item.id).get().join(", ");
$("#result").text(`${ids || "none"} | ${$chosen.length}`);
}
function refresh() {
show($("#menu > li:has(a)"));
}
$("#descendants").on("click", refresh);
$("#children").on("click", () => show($("#menu > li:has(> a)")));
$("#add").on("click", function () {
if (!$("#added-link").length) {
$("#plain").append('<a id="added-link" href="#example"> Added link</a>');
}
refresh();
});
$("#reset").on("click", function () {
$("#added-link").remove();
refresh();
});
refresh();
});
</script>
</body>
</html>
Anfangs werden die äußeren Rahmen von direct und nested markiert:
direct, nested | 2
Direkte Kinder, Einfügen und Zurücksetzen prüfen
- Any descendant link akzeptiert Links in jeder Tiefe:
direct, nested | 2. - Direct child link prüft nur unmittelbare a-Kinder:
direct | 1. Bei nested liegt der Link unter span. - Add a link to plain fügt einen Link ein und ergibt
plain, direct, nested | 3. Ein erneuter Klick prüft dessen ID und erzeugt kein Duplikat. - Reset entfernt nur den zusätzlichen Beispiellink und wendet die ursprüngliche Nachfahrenbedingung an. No link und alle ursprünglichen Elemente bleiben bestehen; wieder passen zwei Einträge.
show entfernt zunächst frühere Markierungen. refresh fragt die aktuelle Struktur erneut ab. Dadurch verwenden Sie nach dem Einfügen keine veraltete Auswahl und behalten bei einem Bedingungswechsel keine unzutreffenden Hervorhebungen.
.has() und .find() vergleichen
Ist die li-Menge bereits ausgewählt, kann die Methode .has() die benötigten Kandidaten behalten. Führen Sie direkt nach dem Öffnen oder nach Reset diesen Teilcode in der Entwicklerkonsole aus:
const ids = $set => $set.map((_, item) => item.id).get().join(", ");
console.log(ids($("#menu > li:has(a)")));
console.log(ids($("#menu > li").has("a")));
console.log(ids($("#menu > li").find("a")));
direct, nested
direct, nested
link-1, link-2
Die ersten beiden Ergebnisse sind IDs der äußeren li, während .find() IDs der inneren a liefert. .has() steigt nicht zu bislang unbekannten Eltern auf, sondern filtert die vorhandene Auswahl anhand von Nachfahren. .filter() prüft dagegen die Kandidaten selbst.
.has() akzeptiert einen Selektorstring oder ein konkretes Element des Document Object Model (DOM). Auch bei einem Elementargument bleiben nur Kandidaten erhalten, die es als Nachfahren enthalten. Passt ausschließlich der Kandidat selbst oder kein Nachfahre, ist das Ergebnis leer.
Bereich, erneute Abfrage und CSS
Ein unbeschränktes $(":has(a)") kann mehrere Vorfahren mit Links erfassen. Begrenzen Sie Container und Tag passend zur Aufgabe. Die Auswahl aktualisiert sich nicht automatisch; nach Hinzufügen oder Entfernen von Nachfahren müssen Sie erneut abfragen.
Selectors Level 4 definiert auch CSS :has(). Die Schreibweise generell als ausschließlich jQuery-spezifisch darzustellen wäre daher ungenau. Hier geht es um Elementmengen über die jQuery-API. Beim Vergleich mit rein gestalterischen CSS-Regeln prüfen Sie die unterstützten Browser und benötigten Selektorbedingungen.
Kontrollieren Sie bei Problemen die jQuery-Anfrage in Network und Fehler in Console. Prüfen Sie Klammern, Anführungszeichen, tatsächliche Tags und Verschachtelung. Entscheidend sind echte a-Elemente, nicht der sichtbare Text „Link“ oder ein Klassenname.




