359 votes

jQuery, premier enfant de "this".

J'essaie de passer "this" d'un span cliqué à une fonction jQuery qui peut ensuite exécuter jQuery sur le premier enfant de cet élément cliqué. Je n'arrive pas à le faire correctement...

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

Javascript :

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

Comment référencer l'élément :first-child ?

4 votes

Si vous utilisez jQuery, pourquoi ne pas lier les gestionnaires d'événements en utilisant également jQuery ?

2 votes

Parce que les gestionnaires d'événements liés doivent être initialisés dans document.ready(), ce qui accroît les performances (il s'agit d'une application pour IE6). existe-t-il un autre moyen ?

0 votes

Hm pas sûr. La liaison avec jQuery est la méthode standard (si vous utilisez déjà jQuery). Quel type de baisse de performances rencontrez-vous lorsque vous utilisez la fonction jQuery(document).ready(...) ?

538voto

Shog9 Points 82052

Si vous souhaitez appliquer un sélecteur au contexte fourni par un ensemble jQuery existant, essayez l'option fonction find() :

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

Jørn Schou-Rode a fait remarquer que vous ne voulez probablement trouver que le premier descendant direct de l'élément de contexte, d'où le sélecteur d'enfant (>). Il souligne également que vous pourriez tout aussi bien utiliser le fonction children() qui est très similaire à find() mais ne recherche qu'à un niveau de profondeur dans la hiérarchie (ce qui est tout ce dont vous avez besoin...) :

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

1 votes

Merci ! Cela fonctionne parfaitement. J'imagine que les autres méthodes énumérées ci-dessous fonctionneront également.

6 votes

Je crois find() cherche dans tous les descendants, et :first-child peut correspondre à un élément par parent. Par conséquent, cette requête est susceptible de renvoyer plusieurs éléments. Ou est-ce que je me trompe ?

0 votes

@Jørn : vous avez raison, je n'y avais pas pensé. S'il existe une hiérarchie, un sélecteur :first-child non qualifié produira plusieurs résultats.

89voto

Jørn Schou-Rode Points 19947

Utilisez le children fonction avec le :first sélecteur pour obtenir le simple premier enfant de element :

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

0 votes

Element.children()[0].toggleClass("redClass") ;

7 votes

@Zakos : TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'

61voto

manikanta Points 2184

J'ai ajouté jsperf test pour voir la différence de vitesse pour différentes approches pour obtenir le premier enfant (total 1000+ enfants)

donné, notif = $('#foo')

Les moyens de jQuery :

  1. $(":first-child", notif) - 4 304 ops/sec - le plus rapide
  2. notif.children(":first") - 653 ops/sec - 85% plus lent
  3. notif.children()[0] - 1 416 ops/sec - 67% plus lent

Moyens indigènes :

  1. JavaScript natif ele.firstChild - 4,934,323 ops/sec (toutes les approches ci-dessus sont 100% plus lentes par rapport à firstChild )
  2. DOM ele natif de jQery : notif[0].firstChild - 4,913,658 ops/sec

Ainsi, les 3 premières approches de jQuery ne sont pas recommandées, au moins pour le premier enfant (je doute que ce soit le cas pour beaucoup d'autres aussi). Si vous avez un objet jQuery et que vous avez besoin d'obtenir le premier enfant, alors obtenir l'élément DOM natif de l'objet jQuery, en utilisant la référence du tableau [0] (recommandé) o .get(0) et utiliser le ele.firstChild . Cela donne les mêmes résultats que l'utilisation normale de JavaScript.

tous les tests sont effectués dans Chrome Canary build v15.0.854.0

24 votes

En fait, firstChild ne donnera pas les mêmes résultats que la méthode de jQuery. children() ou des requêtes sélectives. firstChild inclura les nœuds de texte, ce qui est rarement souhaité. La méthode de jQuery contents() fonction sera les inclure, mais children() ne le fera pas. Les navigateurs les plus récents prennent en charge firstElementChild qui donnera le premier élément enfant, mais IE < 9 ne le supporte pas. Donc, si vous utilisez firstChild vous devez trouver manuellement le premier enfant du nœud non textuel.

4 votes

$(":first-child", notif) devrait être $(":first", notif) pour le comportement attendu. Le premier renverra tous les descendants de l'élément de première classe.

10voto

theIV Points 12999

Avez-vous essayé

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

Je pense que vous voulez définir votre élément comme un contexte pour votre recherche. Il existe peut-être une meilleure façon de procéder, qu'un autre gourou de jQuery viendra vous présenter :)

3 votes

Cela échouera si element a des petits-enfants

5voto

Alnitak Points 143355

Je viens d'écrire un plugin qui utilise .firstElementChild si possible, et revient à l'itération sur chaque nœud individuel si nécessaire :

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

Ce n'est pas aussi rapide qu'une solution DOM pure, mais en tests jsperf Sous Chrome 24, il était plus rapide de quelques ordres de grandeur que toute autre méthode basée sur un sélecteur jQuery.

1 votes

J'aime ce plugin - mais il y a 2 problèmes : 1) Le plugin script ne peut pas être inclus dans le head car document.body n'est pas encore initialisé, 2) Les performances ne sont bien meilleures que les alternatives que si le nombre de nœuds enfants est très élevé. Pour un petit nombre d'enfants (disons moins de 10), les $('>:first-child',context) est un peu plus rapide. Seul le nombre d'enfants affecte les performances, pas la profondeur.

0 votes

@codefactor bon point sur document.body - Je vais voir ça.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X