jQuery erstes Kind von "this"

317

Ich versuche, "dies" von einem angeklickten Bereich an eine jQuery-Funktion zu übergeben, die dann jQuery für das erste untergeordnete Element des angeklickten Elements ausführen kann. Kann es nicht richtig machen ...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

Wie verweise ich auf das: erste Kind des Elements?

macca1
quelle
4
Wenn Sie jQuery verwenden, warum binden Sie Event-Handler nicht auch mit jQuery?
Vivin Paliath
2
da Bindungsereignishandler in document.ready () initialisiert werden müssen, was einen Leistungseinbruch hinzufügt (dies ist eine App für IE6). oder gibt es einen anderen weg
Macca1
Hm .. nicht sicher. Das Binden mit jQuery ist die Standardmethode (wenn Sie bereits jQuery verwenden). Welche Art von Leistungseinbruch erleben Sie, wenn Sie verwenden jQuery(document).ready(...)?
Vivin Paliath
Es ist eine große Anwendung mit mehr als 7 Entwicklern. Es dauerte ursprünglich mehr als 4 Sekunden, bis ich versuchte, es ein bisschen aufzuräumen. Also würde ich lieber vermeiden, mehr hinzuzufügen, wenn ich nicht muss :)
macca1

Antworten:

482

Wenn Sie einen Selektor auf den Kontext anwenden möchten, der von einem vorhandenen jQuery-Set bereitgestellt wird, versuchen Sie die Funktion find () :

element.find(">:first-child").toggleClass("redClass");

Jørn Schou-Rode bemerkte, dass Sie wahrscheinlich nur den ersten direkten Nachkommen des Kontextelements finden möchten , daher den untergeordneten Selektor (>). Er weist auch darauf hin, dass Sie genauso gut die Funktion children () verwenden könnten , die find () sehr ähnlich ist, aber nur eine Ebene tief in der Hierarchie durchsucht (was alles ist, was Sie brauchen ...):

element.children(":first").toggleClass("redClass");
Shog9
quelle
1
Vielen Dank! funktioniert perfekt. Ich kann mir vorstellen, dass die anderen unten aufgeführten Möglichkeiten ebenfalls funktionieren.
Macca1
6
Ich glaube, find()durchsucht alle Nachkommen und :first-childkann ein Element pro Elternteil zuordnen. Daher kann diese Abfrage wahrscheinlich mehrere Elemente zurückgeben. Oder irre ich mich?
Jørn Schou-Rode
19
Ich weiß, dass dies eine alte Frage / Antwort ist, aber die Verwendung des Selektors ">" ohne übergeordnetes Element in diesem Selektor wird ab jQuery 1.8 abgeschrieben (z. B. ">: firstchild"). Ich schlage vor, stattdessen element.children(":first-child")oderelement.children().first();
Kevin B
3
@ KevinB anscheinend haben sie beschlossen, es doch nicht zu verwerfen
Alnitak
1
Der beste Ansatz wäre, NICHT alle Elemente zu iterieren und dann das erste auszuwählen, wie einige hier vorgeschlagen haben. Das wäre schlecht.
vsync
74

Verwenden Sie die childrenFunktion mit dem :firstWähler das bekommen einzelnes erste Kind element:

element.children(":first").toggleClass("redClass");
Jørn Schou-Rode
quelle
element.children () [0] .toggleClass ("redClass");
Zakos
5
@ Zakos:TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'
Jørn Schou-Rode
51

Ich habe jsperf hinzugefügt Test , um den Geschwindigkeitsunterschied für verschiedene Ansätze zu ermitteln, um das erste Kind zu bekommen (insgesamt 1000+ Kinder).

gegeben, notif = $('#foo')

jQuery-Möglichkeiten:

  1. $(":first-child", notif) - 4.304 Operationen / Sek. - am schnellsten
  2. notif.children(":first") - 653 Ops / Sek. - 85% langsamer
  3. notif.children()[0] - 1.416 Operationen / Sek. - 67% langsamer

Einheimische Wege:

  1. JavaScript native ' ele.firstChild- 4.934.323 ops / s (alle oben genannten Ansätze sind 100% langsamer alsfirstChild )
  2. Native DOM ele von jQery: notif[0].firstChild- 4.913.658 Operationen / Sek

Daher werden die ersten drei jQuery-Ansätze zumindest für das erste Kind nicht empfohlen (ich bezweifle, dass dies auch bei vielen anderen der Fall ist). Wenn Sie ein jQuery-Objekt haben und das erste untergeordnete Objekt abrufen müssen, rufen Sie das native DOM-Element aus dem jQuery-Objekt ab, indem Sie die Array-Referenz [0] (empfohlen) oder .get(0)verwenden ele.firstChild. Dies führt zu denselben identischen Ergebnissen wie die normale Verwendung von JavaScript.

Alle Tests werden in Chrome Canary Build v15.0.854.0 durchgeführt

Manikanta
quelle
20
Tatsächlich firstChildwerden nicht die gleichen Ergebnisse wie bei jQuery- children()oder Selektorabfragen erzielt . firstChildenthält Textknoten, was selten erwünscht ist. Die contents()Funktion von jQuery wird sie einschließen, aber children()nicht. Neuere Browser unterstützen firstElementChilddas erste untergeordnete Element, IE <9 unterstützt es jedoch nicht. Wenn Sie also verwenden firstChild, müssen Sie das erste untergeordnete Nicht-Textknoten manuell finden.
Max
1
$(":first-child", notif)sollte $(":first", notif)für erwartetes Verhalten sein. Ersteres gibt alle Nachkommen des ersten untergeordneten Elements zurück.
Drazen Bjelovuk
18
element.children().first();

Finde alle Kinder und hol dir die ersten.

Bishal Paudel
quelle
1
Bei weitem die einfachste Methode und effizienter als .children(':first').
Gras Double
3
Wie ist es effizienter? Es scheint, dass es alle Kinder bekommt, dann nimmt es das erste, anstatt nur das erste Kind zu bekommen.
Anthony McGrath
9

Hast du es versucht

$(":first-child", element).toggleClass("redClass");

Ich denke, Sie möchten Ihr Element als Kontext für Ihre Suche festlegen. Es könnte einen besseren Weg geben, dies zu tun, den ein anderer jQuery-Guru hier einspringen und auf dich werfen wird :)

theIV
quelle
3
dies wird scheitern , wenn elementEnkelkinder hat
Alnitak
4

Ich habe gerade ein Plugin geschrieben, das .firstElementChildwenn möglich verwendet und bei Bedarf auf die Iteration jedes einzelnen Knotens zurückgreift:

(function ($) {
    var useElementChild = ('firstElementChild' in document.createElement('div'));

    $.fn.firstChild = function () {
        return this.map(function() {
            if (useElementChild) {
                return this.firstElementChild;
            } else {
                var node = this.firstChild;
                while (node) {
                    if (node.type === 1) {
                        break;
                    }
                    node = node.nextSibling;
                }
                return node;
            }
        });
    };
})(jQuery);

Es ist nicht so schnell wie eine reine DOM-Lösung, aber in jsperf-Tests unter Chrome 24 war es einige Größenordnungen schneller als jede andere auf jQuery-Selektoren basierende Methode.

Alnitak
quelle
1
Ich mag dieses Plugin - aber es gibt zwei Probleme: 1) Das Plugin-Skript kann nicht in den Kopf aufgenommen werden, da document.bodyes noch nicht initialisiert ist. 2) Die Leistung ist nur dann viel besser als bei Alternativen, wenn die Anzahl der untergeordneten Knoten sehr hoch ist. Für nur wenige Kinder (sagen wir weniger als 10) $('>:first-child',context)ist das etwas schneller. Nur die Anzahl der Kinder beeinflusst die Leistung, nicht die Tiefe.
Codefaktor
@codefactor guter Punkt über document.body- ich werde das untersuchen.
Alnitak
4

Sie können DOM verwenden

$(this).children().first()
// is equivalent to
$(this.firstChild)
Yukulélé
quelle
1

Bitte benutze es wie folgt. Gib als erstes einen Klassennamen, um p wie "myp" zu markieren.

Verwenden Sie dann den folgenden Code

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})
Vishal Gupta
quelle
-3

Wenn Sie sofort das erste Kind wollen, brauchen Sie

    $(element).first();

Wenn Sie ein bestimmtes erstes Element im Dom von Ihrem Element möchten, verwenden Sie unten

    var spanElement = $(elementId).find(".redClass :first");
    $(spanElement).addClass("yourClassHere");

Probieren Sie es aus: http://jsfiddle.net/vgGbc/2/

Amit Rathod
quelle
11
Dies ist einfach falsch - wenn elementes sich um einen DOM-Knoten $(element).first()handelt, entspricht dies $(element)nicht seinem ersten untergeordneten Knoten .
Alnitak
1
Einverstanden, wenn Element ein DOM-Knoten ist $ (Element) .first () ist äquivalent $ (Element), verursachte dies ein Problem mit der KnockoutJS-Bindung
drgn