jQuery premier enfant de «this»

317

J'essaye de passer "ceci" d'une étendue cliquée à une fonction jQuery qui peut ensuite exécuter jQuery sur le premier enfant de l'élément cliqué. Je n'arrive pas à faire les choses correctement ...

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

Javascript:

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

Comment référencer le: premier enfant de l'élément?

macca1
la source
4
Si vous utilisez jQuery, pourquoi ne liez-vous pas également les gestionnaires d'événements à l'aide de jQuery?
Vivin Paliath
2
car les gestionnaires d'événements de liaison doivent être initialisés dans document.ready (), ce qui ajoute un impact sur les performances (il s'agit d'une application pour IE6). ou existe-t-il un autre moyen?
macca1
Hm .. pas sûr. La liaison à l'aide de jQuery est la méthode standard (si vous utilisez déjà jQuery). Quel type de performance rencontrez-vous lorsque vous utilisez jQuery(document).ready(...)?
Vivin Paliath
C'est une grande application avec plus de 7 développeurs. C'était à l'origine 4+ secondes avant d'essayer de le nettoyer un peu. Je préfère donc éviter d'en ajouter plus quand je n'ai pas à le faire :)
macca1

Réponses:

482

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

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

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

element.children(":first").toggleClass("redClass");
Shog9
la source
1
Merci! fonctionne parfaitement. J'imagine que les autres façons énumérées ci-dessous fonctionneront également.
macca1
6
Je crois que les find()recherches dans tous les descendants :first-childpeuvent correspondre à un élément par parent. Par conséquent, cette requête peut renvoyer plusieurs éléments. Ou je me trompe?
Jørn Schou-Rode
19
Je sais que c'est une vieille question / réponse, mais l'utilisation du sélecteur ">" sans parent dans ce sélecteur est dépréciée (par exemple, ">: firstchild") à partir de jQuery 1.8. Je suggère plutôt d'utiliser element.children(":first-child")ouelement.children().first();
Kevin B
3
@KevinB apparemment, ils ont décidé de ne pas le déprécier après tout
Alnitak
1
la meilleure approche serait de NE PAS répéter tous les éléments, puis de choisir le premier, comme certains l'ont suggéré ici. Ce serait MAUVAIS.
vsync
74

Utilisez la childrenfonction avec le :firstsélecteur pour obtenir le premier enfant unique de element:

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

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

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

jQuery façons:

  1. $(":first-child", notif) - 4304 ops / sec - le plus rapide
  2. notif.children(":first") - 653 ops / sec - 85% plus lent
  3. notif.children()[0] - 1416 opérations / sec - 67% plus lent

Voies natives:

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

Ainsi, les 3 premières approches jQuery ne sont pas recommandées, du 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 devez obtenir le premier enfant, récupérez l'élément DOM natif de l'objet jQuery, en utilisant la référence de tableau [0] (recommandé) ou .get(0)et utilisez le ele.firstChild. Cela donne les mêmes résultats identiques que l'utilisation régulière de JavaScript.

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

manikanta
la source
20
En fait, firstChildne donnera pas les mêmes résultats que les children()requêtes jQuery ou sélecteur. firstChildcomprendra des nœuds de texte, ce qui est rarement souhaité. jQuery contents()fonction sera les inclure, mais children()ne sera pas. Les navigateurs plus récents prennent en charge firstElementChildce qui donnera le premier élément enfant, mais IE <9 ne le prend pas en charge. Donc, si vous utilisez, firstChildvous devez rechercher manuellement le premier enfant de nœud non textuel.
Max
1
$(":first-child", notif)devrait être $(":first", notif)pour le comportement attendu. Le premier retournera tous les descendants du premier élément enfant.
Drazen Bjelovuk
18
element.children().first();

Trouvez tous les enfants et prenez le premier.

Bishal Paudel
la source
1
De loin la méthode la plus simple, et plus efficace que .children(':first').
Gras Double
3
Comment est-il plus efficace? Il semble que tous les enfants soient capturés, puis le premier, par opposition au premier enfant.
Anthony McGrath
9

As-tu essayé

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

Je pense que vous voulez définir votre élément comme contexte pour votre recherche. Il pourrait y avoir une meilleure façon de le faire qu'un autre gourou de jQuery va sauter ici et vous lancer :)

theIV
la source
3
cela échouera si elementa des petits-enfants
Alnitak
4

Je viens d'écrire un plugin qui utilise .firstElementChildsi possible, et revient à itérer 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 dans les tests jsperf sous Chrome 24, c'était deux fois plus rapide que toute autre méthode basée sur le sélecteur jQuery.

Alnitak
la source
1
J'aime ce plugin - mais il y a 2 problèmes: 1) Le script du plugin ne peut pas être inclus dans la tête car il document.bodyn'est pas encore initialisé, 2) Les performances ne sont bien meilleures que les alternatives si le nombre de nœuds enfants est très élevé. Pour seulement quelques enfants (disons moins de 10 ans), $('>:first-child',context)c'est un peu plus rapide. Seul le nombre d'enfants affecte la performance, pas la profondeur.
codefactor
@codefactor bon point à propos de document.body- je vais examiner cela.
Alnitak
4

vous pouvez utiliser DOM

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

veuillez l'utiliser comme cette première chose donnez un nom de classe à la balise p comme "myp"

puis utiliser le code suivant

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

Si vous voulez un premier enfant immédiat dont vous avez besoin

    $(element).first();

Si vous voulez un premier élément particulier dans le dom de votre élément, utilisez ci-dessous

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

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

Amit Rathod
la source
11
c'est tout simplement faux - si elementest un nœud DOM, il $(element).first()est équivalent à $(element), pas son premier enfant.
Alnitak
1
D'accord, si l'élément est un nœud DOM $ (element) .first () est équivalent à $ (element) cela m'a causé un problème avec la liaison knockoutJS
drgn