jQuery primo figlio di "questo"


317

Sto cercando di passare "questo" da un intervallo di clic a una funzione jQuery che può quindi eseguire jQuery sul primo figlio dell'elemento selezionato. Non riesco a farlo bene ...

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

Javascript:

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

Come posso fare riferimento a: first-child of element?


4
Se stai usando jQuery, perché non associ anche i gestori di eventi usando jQuery?
Vivin Paliath,

2
perché i gestori di eventi bind devono essere inizializzati in document.ready () che aggiunge un hit di prestazione (questa è un'app per IE6). oppure c'è un'altro modo?
macca1,

Hm .. non ne sono sicuro. Associare usando jQuery è il modo standard (se stai già usando jQuery). Che tipo di prestazioni hai riscontrato durante l'utilizzo jQuery(document).ready(...)?
Vivin Paliath,

È una grande applicazione con oltre 7 sviluppatori. In origine erano passati più di 4 secondi prima che provassi a ripulirlo un po '. Quindi preferirei evitare di aggiungere altro quando non devo :)
macca1

Risposte:


482

Se si desidera applicare un selettore al contesto fornito da un set jQuery esistente, provare la funzione find () :

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

Jørn Schou-Rode ha notato che probabilmente vuoi solo trovare il primo discendente diretto dell'elemento di contesto, quindi il selettore figlio (>). Sottolinea inoltre che è possibile utilizzare la funzione children () , che è molto simile a find () ma cerca solo un livello in profondità nella gerarchia (che è tutto ciò che serve ...):

element.children(":first").toggleClass("redClass");

1
Grazie! funziona perfettamente. Immagino che funzioneranno anche gli altri modi elencati di seguito.
macca1,

6
Credo che effettui find()ricerche in tutti i discendenti e :first-childpossa corrispondere a un elemento per genitore. Pertanto, è possibile che questa query restituisca diversi elementi. O mi sbaglio?
Jørn Schou-Rode,

19
So che questa è una vecchia domanda / risposta, ma l'utilizzo del selettore ">" senza un genitore in quel selettore è deprezzato (ad esempio, ">: firstchild") a partire da jQuery 1.8. Suggerisco invece di utilizzare element.children(":first-child")oelement.children().first();
Kevin B,

3
@KevinB a quanto pare hanno deciso di non deprecarlo dopo tutto
Alnitak,

1
l'approccio migliore NON sarebbe quello di iterare su tutti gli elementi e quindi scegliere il primo, come alcuni hanno suggerito qui. Questo sarebbe MALE.
vsync,


51

Ho aggiunto il test jsperf per vedere la differenza di velocità per diversi approcci per ottenere il primo figlio (totale 1000+ bambini)

dato, notif = $('#foo')

modi jQuery:

  1. $(":first-child", notif) - 4.304 ops / sec - più veloce
  2. notif.children(":first") - 653 operazioni / sec - 85% più lento
  3. notif.children()[0] - 1.416 operazioni / sec - 67% più lento

Modi nativi:

  1. JavaScript nativo ' ele.firstChild- 4.934.323 ops / sec (tutti gli approcci precedenti sono più lenti del 100% rispetto a firstChild)
  2. Ele DOM nativo di jQery: notif[0].firstChild- 4.913.658 ops / sec

Quindi, i primi 3 approcci jQuery non sono raccomandati, almeno per il primo figlio (dubito che sarebbe così anche per molti altri). Se si dispone di un oggetto jQuery e è necessario ottenere il primo figlio, quindi ottenere l'elemento DOM nativo dall'oggetto jQuery, utilizzando il riferimento di matrice [0] (consigliato) oe .get(0)utilizzare ele.firstChild. Ciò fornisce gli stessi risultati identici del normale utilizzo di JavaScript.

tutti i test vengono eseguiti in Chrome Canary build v15.0.854.0


20
In realtà, firstChildnon darà gli stessi risultati delle children()query di jQuery o dei selettori. firstChildincluderà nodi di testo raramente desiderati. La contents()funzione di jQuery li includerà, ma children()non lo farà. Supporto per i browser più recenti firstElementChildche fornirà il primo elemento figlio, ma IE <9 non lo supporta. Quindi, se lo usi firstChilddevi trovare manualmente il primo figlio nodo non testuale.
Max

1
$(":first-child", notif)dovrebbe essere $(":first", notif)per il comportamento previsto. Il primo restituirà tutti i discendenti degli elementi del primo figlio.
Drazen Bjelovuk,

18
element.children().first();

Trova tutti i bambini e ottieni prima di loro.


1
Di gran lunga il metodo più semplice e più efficiente di .children(':first').
Gras Double

3
Come è più efficiente? Sembra che prende tutti i bambini, quindi prende il primo, invece di ottenere solo il primo figlio.
Anthony McGrath,

9

Hai provato

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

Penso che tu voglia impostare il tuo elemento come contesto per la tua ricerca. Potrebbe esserci un modo migliore per farlo che qualche altro guru di jQuery salterà qui e ti lancerà fuori :)


3
questo fallirà se elementha dei nipoti
Alnitak,

4

Ho appena scritto un plug-in che utilizza .firstElementChildse possibile e, se necessario, ricorre all'iterazione su ogni singolo nodo:

(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);

Non è veloce come una soluzione DOM pura, ma nei test jsperf con Chrome 24 era un paio di ordini di grandezza più veloce di qualsiasi altro metodo basato su selettori jQuery.


1
Mi piace questo plugin - ma ci sono 2 problemi: 1) Lo script del plugin non può essere incluso nella testa perché document.bodynon è ancora inizializzato, 2) Le prestazioni sono solo molto meglio delle alternative se il numero di nodi figlio è molto alto. Solo per alcuni bambini (diciamo meno di 10) $('>:first-child',context)è un po 'più veloce. Solo il numero di bambini influenza le prestazioni, non la profondità.
codefactor

@codefactor buon punto a riguardo document.body- lo esaminerò.
Alnitak,

4

puoi usare DOM

$(this).children().first()
// is equivalent to
$(this.firstChild)


1

per favore usalo come questa prima cosa dai un nome di classe per taggare p come "myp"

quindi utilizzare il seguente codice

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

-3

Se vuoi il primo figlio immediato, ti serve

    $(element).first();

Se vuoi un primo elemento particolare nel dom dal tuo elemento, usa di seguito

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

prova: http://jsfiddle.net/vgGbc/2/


11
questo è solo sbagliato - se elementè un nodo DOM allora $(element).first()è equivalente $(element), non il suo primo figlio.
Alnitak,

1
D'accordo, se element è un nodo DOM $ (element) .first () equivale a $ (element) questo mi ha causato un problema con l'associazione knockoutJS
drgn
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.