44 votes

Comment est évalué le sélecteur jQuery $('#foo a') ?

Voici un exemple de code jQuery ( https://coderwall.com/p/7uchvg ), je lis que l'expression $('#foo a'); se comporte ainsi :

Trouvez chaque a dans la page et ensuite filtrer a à l'intérieur de #foo .

Et ça n'a pas l'air efficace.

Est-ce exact ? Et si oui, comment pouvons-nous mieux le faire ?

50voto

Chris Heald Points 28814

C'est exact - Sizzle (le moteur de sélection de jQuery) se comporte de la manière suivante de la même manière que les sélecteurs CSS . Les sélecteurs CSS et Sizzle sont évalué de droite à gauche et ainsi de suite #foo a trouvera tous les a puis filtrer ces derniers par les nœuds qui descendent de #foo .

Vous améliorez ce résultat en veillant à ce que vos sélecteurs de feuilles aient une spécificité élevée, généralement en leur donnant une classe ou un ID.

19voto

Andries Points 698

comment pouvons-nous mieux le faire ?

Utilisez le paramètre contextuel de jQuery.

$('a', '#foo');

Maintenant, jQuery va rechercher toutes les ancres dans le contexte de l'élément avec id : foo.

Dans votre requête, le contexte est défini par défaut comme document lorsqu'il est omis :

$('#foo a'); == $('#foo a', document); 

Dans ce cas, votre requête n'est effectivement pas efficace.

Vous pourriez jeter un coup d'oeil à cet article .

5voto

timmywil Points 161

S'il est vrai que Sizzle est un moteur qui fonctionne de droite à gauche (ce qui correspond à la manière dont le CSS est interprété), il n'est pas vrai que le sélecteur spécifique de votre exemple sélectionnerait tous les éléments d'ancrage de la page, puis filtrerait leurs parents pour qu'ils correspondent à l'id de "foo". Sizzle optimise en fait tout sélecteur qui commence par un ID et l'utilise comme contexte pour l'ensemble de la sélection, plutôt que d'utiliser le document. En d'autres termes, le sélecteur que vous avez choisi se traduit essentiellement par :

document.getElementById("foo").getElementsByTagName("a")

Vraiment, ce n'est pas un mauvais sélecteur du tout.

Toutefois, compte tenu des autres opérations que jQuery doit effectuer (notamment le bouclage des éléments pour les fusionner dans l'instance jQuery), jQuery("#foo").find("a") sera toujours le plus rapide car jQuery met en œuvre un raccourci de création d'objet jQuery pour les sélecteurs id-only, puis effectue la recherche à partir de #foo.

En d'autres termes, Sizzle lui-même n'est pas très différent lorsqu'il fait Sizzle("#foo a") y Sizzle("a", document.getElementById("foo")) mais jQuery("#foo").find... sera plus rapide grâce au raccourci ID propre à jQuery.

À propos, mes remarques sur Sizzle supposent que querySelectorAll n'est pas utilisé. Si c'est le cas, Sizzle le transmet simplement à qsa, ce qui n'est toujours pas aussi rapide que d'utiliser le raccourci ID de jQuery.

4voto

Christophe Points 7878

Vous pouvez utiliser find() pour un contrôle plus granulaire de l'ordre de votre sélecteur :

$('#foo').find('a');

Cela sera bien sûr plus impressionnant avec des sélecteurs plus complexes, où vous pouvez enchaîner find() et filter().

Pour mémoire $('#foo').find('a') === $('a','#foo')

[Mise à jour] ok, j'ai réalisé plus tard que c'est exactement ce que votre lien dit...

Le moteur de sélection de jQuery (Sizzle) a été refactorisé l'année dernière, vous trouverez des explications détaillées ici : http://www.wordsbyf.at/2011/11/23/selectors-selectoring/

2voto

Murali Prasanth Points 1750

Au lieu de filtrer avec a à l'intérieur de #foo il suffit d'attacher une classe à a et obtenir a éléments avec une classe comme $("a.class"); . Ce serait plus efficace.

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