Ich kann das:
<div id="myDiv">
<div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
Das heißt, ich kann erfolgreich alle direkten untergeordneten myDiv
Elemente des Elements mit Klasse abrufen .foo
.
Das Problem ist, es stört mich, dass ich das #myDiv
in den Selektor aufnehmen muss, weil ich die Abfrage für das myDiv
Element ausführe (es ist also offensichtlich redundant).
Ich sollte in der Lage sein, das #myDiv
Aus zu lassen, aber dann ist der Selektor keine legale Syntax, da er mit a beginnt >
.
Weiß jemand, wie man einen Selektor schreibt, der nur die direkten untergeordneten Elemente des Elements erhält, auf dem der Selektor ausgeführt wird?
javascript
dom
css-selectors
mattsh
quelle
quelle
Antworten:
Gute Frage. Zu der Zeit, als es gefragt wurde, gab es keine universell implementierte Möglichkeit, "kombinatorisch verwurzelte Abfragen" (wie John Resig sie nannte ) durchzuführen .
Nun wurde die Pseudoklasse: scope eingeführt. Es wird in [Pre-Chrominum] -Versionen von Edge oder IE nicht unterstützt , wird jedoch bereits seit einigen Jahren von Safari unterstützt. Damit könnte Ihr Code werden:
Beachten Sie, dass Sie in einigen Fällen auch
.querySelectorAll
andere gute, altmodische DOM-API-Funktionen überspringen und verwenden können. Zum BeispielmyDiv.querySelectorAll(":scope > *")
könnten Sie stattdessen einfach schreibenmyDiv.children
.Andernfalls, wenn Sie sich noch nicht darauf verlassen können
:scope
, kann ich mir keinen anderen Weg vorstellen, um mit Ihrer Situation umzugehen, ohne mehr benutzerdefinierte Filterlogik hinzuzufügen (z. B.myDiv.getElementsByClassName("foo")
deren zu finden.parentNode === myDiv
), und natürlich nicht ideal, wenn Sie versuchen, einen Codepfad wirklich zu unterstützen Ich möchte nur eine beliebige Auswahlzeichenfolge als Eingabe und eine Liste von Übereinstimmungen als Ausgabe verwenden! Aber wenn Sie wie ich diese Frage gestellt haben, nur weil Sie nicht weiter dachten: "Alles, was Sie hatten, war ein Hammer", vergessen Sie nicht, dass das DOM auch eine Vielzahl anderer Tools anbietet.quelle
myDiv.getElementsByClassName("foo")
ist nicht dasselbe wiemyDiv.querySelectorAll("> .foo")
, es ist eher somyDiv.querySelectorAll(".foo")
(was übrigens tatsächlich funktioniert), dass es alle Nachkommen findet.foo
und nicht nur Kinder.<style scoped>
) haben nichts mit dem:scope
in dieser Antwort beschriebenen Pseudo-Selektor zu tun .Die richtige Methode zum Schreiben eines Selektors, der im aktuellen Element "verwurzelt" ist, ist die Verwendung
:scope
.Die Browserunterstützung ist jedoch begrenzt und Sie benötigen eine Unterlegscheibe, wenn Sie sie verwenden möchten. Zu diesem Zweck habe ich scopedQuerySelectorShim erstellt .
quelle
:scope
Spezifikation derzeit ein "Arbeitsentwurf" ist und sich daher ändern kann. Es ist wahrscheinlich, dass es immer noch so funktioniert, wenn es angenommen wird, aber ein bisschen früh zu sagen, dass dies meiner Meinung nach der "richtige Weg" ist, dies zu tun.Hier ist eine flexible Methode, die in Vanilla JS geschrieben ist und es Ihnen ermöglicht, eine CSS-Selektorabfrage nur über die direkten untergeordneten Elemente eines Elements auszuführen:
quelle
Math.random().toString(36).substr(2, 10)
, dass derselbe Token mehr als einmal erzeugt wird.any dupe would need to also be a child of the same parent node
,id
Attribute sind dokumentweit. Sie haben Recht, die Chancen sind immer noch vernachlässigbar, aber danke, dass Sie die Hauptstraße genommen und diesen Zähler hinzugefügt haben :)Wenn Sie sicher sind, dass das Element eindeutig ist (z. B. Ihr Fall mit der ID):
Für eine "globalere" Lösung: (Verwenden Sie einen Matchselector-Shim )
Wo
elm
ist Ihr übergeordnetes Element undsel
ist Ihr Selektor. Könnte auch als Prototyp verwendet werden.quelle
matchesSelector
ohne Präfix (die nicht einmal Arbeit in der neuesten Version von Chrome), verschmutzen sie den globalen Namensraum (ret wurde nicht erklärt), ist es nicht zurückgeben NodeList wie querySelectorMethods zu erwarten sind. Ich denke nicht, dass es eine gute Lösung ist, daher die Ablehnung.Die folgende Lösung unterscheidet sich von den bisher vorgeschlagenen und funktioniert für mich.
Das Grundprinzip ist, dass Sie zuerst alle übereinstimmenden Kinder auswählen und dann diejenigen herausfiltern, die keine direkten Kinder sind. Ein Kind ist ein direktes Kind, wenn es kein übereinstimmendes Elternteil mit demselben Selektor hat.
HTH!
quelle
Ich habe eine Funktion erstellt, um mit dieser Situation umzugehen, und dachte, ich würde sie teilen.
Im Wesentlichen generieren Sie eine Zufallszeichenfolge (die randomString-Funktion ist hier ein importiertes npm-Modul, aber Sie können Ihre eigene erstellen.). Verwenden Sie dann diese Zufallszeichenfolge, um sicherzustellen, dass Sie das erwartete Element im Selektor erhalten. Dann können Sie das
>
danach verwenden.Der Grund, warum ich das ID-Attribut nicht verwende, ist, dass das ID-Attribut möglicherweise bereits verwendet wird und ich dies nicht überschreiben möchte.
quelle
Nun, wir können problemlos alle direkten untergeordneten Elemente eines Elements verwenden
childNodes
und Vorfahren mit einer bestimmten Klasse mit auswählen.querySelectorAll
Es ist also nicht schwer vorstellbar, dass wir eine neue Funktion erstellen können, die beides erhält und beide vergleicht.Hinweis: Dies gibt ein Array von Knoten zurück, keine NodeList.
Verwendung
quelle
Ich möchte hinzufügen, dass Sie die Kompatibilität von : scope erweitern können, indem Sie dem aktuellen Knoten nur ein temporäres Attribut zuweisen.
quelle
Ich wäre mitgegangen
quelle
Ich mache das nur, ohne es zu versuchen. Würde das funktionieren?
Probieren Sie es aus, vielleicht funktioniert es vielleicht nicht. Apolovies, aber ich bin jetzt nicht auf einem Computer, um es zu versuchen (Antwort von meinem iPhone).
quelle