web-dev-qa-db-fra.com

Différence entre: caché et: pas (: visible) dans jQuery

Je sais que les deux sélecteurs jQuery correspondent à des éléments qui ne sont pas visibles (width ou height égal à 0, display: none, parent avec display: none), et je pense qu'il est implicite qu'ils devraient donner le même résultat dans thedocs .

Pour des raisons de lisibilité, je préfère utiliser :hidden mais je veux savoir:

  • Y a-t-il des pièges potentiels que je devrais considérer?
  • Vais-je toujours obtenir exactement le même résultat?
  • Quelle option a de meilleures performances?
33
Meryovi
  • EDIT 22/03/2016: ajouter à la réponse re: jQuery 1.12/2.2 et 3.0 (* voir fin de réponse)
  • EDIT 3/8/2016: améliorer la réponse

Les éléments peuvent être considérés comme cachés pour plusieurs raisons:

  • Ils ont une valeur CSS display de none.
  • Ce sont des éléments de formulaire avec type="hidden".
  • Leur largeur et leur hauteur sont explicitement définies sur 0.
  • Un élément ancêtre est masqué, donc l'élément n'est pas affiché sur la page.

Les éléments avec visibility: hidden Ou opacity: 0 Sont considérés comme visibles, car ils consomment toujours de l'espace dans la mise en page. Lors des animations qui cachent un élément, l'élément est considéré comme visible jusqu'à la fin de l'animation.

Les éléments qui ne figurent pas dans un document ne sont pas considérés comme visibles; jQuery n'a aucun moyen de savoir s'ils seront visibles lorsqu'ils seront ajoutés à un document car cela dépend des styles applicables.

Le sélecteur :hidden Est l'opposé du sélecteur :visible. Ainsi, chaque élément sélectionné par :hidden N'est pas sélectionné par :visible Et vice versa.

Lors des animations pour montrer un élément, l'élément est considéré comme visible au début de l'animation.

La façon dont :hidden Est déterminé a été modifiée dans jQuery 1.3.2. Un élément est supposé être caché si lui ou l'un de ses parents ne consomme pas d'espace dans le document . La visibilité CSS n'est pas prise en compte


Clarification "largeur ou hauteur égale à 0" - pas strictement vrai car certains navigateurs (opéra) rapportent moins de 0 dans certains cas, donc jQuery utilise <=0 En interne.

  1. Y a-t-il des pièges potentiels que je devrais considérer?
  2. Vais-je toujours obtenir exactement le même résultat?
  3. Quelle option a de meilleures performances?

1: Les "pièges" autres qu'évidents dont je ne connais aucun, sont quelque peu subjectifs. Je dis cela en essayant d'éviter les tests "négatifs" dans le code (pas les vérifications de type x ou! X) car les vérifications d'égalité sont plus intuitives pour que mon cerveau les comprenne.

2: Oui, le résultat devrait être le même

3: Re: Différence de performances entre: RE: 1.10.1 version

La vérification de l'état visible utilise le non masqué en interne:

jQuery.expr.filters.visible = function( elem ) {
    return !jQuery.expr.filters.hidden( elem );
};

On pourrait donc dire qu'à proprement parler "caché" devrait être plus efficace en évitant la condition "non".

En interne, jQuery utilise un sélecteur "de droite à gauche" afin que le sélecteur fasse plus de différence dans certains cas.

Pour les performances, utilisez

$(selector).filter(':hidden')

ou

$(selector).not(':visible') 

plutôt que l'un ou l'autre

$('selector:not(:visible)') 

ou

$('selector:hidden')

Pourquoi est-ce? :hidden Est une extension jQuery et ne peut donc pas profiter de l'amélioration des performances fournie par la méthode native DOM querySelectorAll(). (voir l'analyse de droite à gauche du moteur Sizzle pour savoir comment cela se produira)

Formes/format du sélecteur

En effet, pour la forme $('selector:hidden'), il sélectionnera (en parcourant le DOM)

  1. tous les éléments cachés d'abord,
  2. puis sélectionnez ceux correspondant au sélecteur de cet ensemble. Il serait préférable de faire correspondre le sélecteur en premier , puis filtrer ceux de cet ensemble qui sont cachés.

fonction interne "isHidden": (jQuery 1.10.1)

function isHidden( elem, el ) {
    // isHidden might be called from jQuery#filter function;
    // in that case, element will be second argument
    elem = el || elem;
    return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
}

Utilisé par exemple dans le .showHide En interne comme:

if ( elem.style.display === "" && isHidden( elem ) ) {

Il convient de noter que l'attribut "caché" dans defaultPrefilter est:

hidden = elem.nodeType && isHidden( elem ),

Note spéciale sur style:

Définition d'un CSS d'éléments comme:

document.getElementById("hide-me").style.visibility = "hidden";

est très rapide.

Vous pouvez également détecter cela très rapidement:

document.getElementById("hide-me").style.visibility  === "hidden";

Souvenez-vous cependant que l'élément prend toujours de la place alors que document.getElementById("hide-me").style.display = "block"; semble le rendre visible mais gardez à l'esprit que certains PARENT pourraient NE PAS être visibles ainsi l'élément pourrait toujours être considéré "caché" - et jQuery le détecte (voir ci-dessus)

Référence supplémentaire: https://api.jquery.com/hidden-selector/

Informations supplémentaires concernant jQuery 1.12/2.2 et 3.0 22/03/2016 Modifier

Il y a eu quelques améliorations significatives de vitesse dans ces versions.

Ce changement peut donner jusqu'à 1600% d'améliorations de vitesse wow! En profitant de la mise en cache lorsque cela est possible - ce qui d'après ce que j'ai observé se produit souvent avec ces sélecteurs. Testez vos pages avec les deux si vous avez besoin d'améliorations ou de préoccupations dans ce domaine et utilisez les cas s'ils sont fortement utilisés dans vos pages.

Vous devriez voir des performances améliorées avec .show() et .hide() en conséquence.

jQuery 1.12+ et 2.2.0+ et 3.0 modifient la signification des filtres :visible et :hidden. Les éléments seront considérés :visible S'ils ont des boîtes de mise en page. Cela inclut ceux dont la largeur et/ou la hauteur sont nulles. Pour vos sélecteurs, méfiez-vous du nombre. Exemples: les éléments en ligne sans contenu et les éléments br seront désormais sélectionnés par le filtre :visible.

Exemples de balisage de page:

<div>
</div>
<span></span>
<br />
<p>
</p>

Avec le secteur suivant:

var visibleElementCount = $('body').find(':visible').length;
  • Dans jQuery 1.11.1 et 2.1.4, retourne la valeur 2 pour visibleElementCount
  • Dans jQuery 1.12+ et 2.2.0+ et 3.0, vous obtiendrez 4 pour visibleElementCount. Testez lorsque vous comptez sur ce fait car cela peut être un changement de rupture pour vos pages.
47
Mark Schultheiss

Hum ... intéressant :)

:hidden = :not(:visible) = css selector 'display: none;'

Maintenant quelques autres faits:

sélecteur css 'visibility: hidden;' = 'opacity: 0;' = not display dans la page mais occupy space.

sélecteur css 'display: none;' = not showing in page et aussi not occupying space.

par jQuery vous pouvez jouer avec des éléments qui ont 'display: none' style

Exemple HTML:

<input type='text' class='display' value='Display' />

Exemple CSS:

.display{
  display: none;
}

Vérifiez:

alert($('.display').val());// Display

$('.display').val('Hello');

alert($('.display').val());// Hello
5
Neeraj Singh

Ils agiront tous les deux de la même manière sans aucune différence concevable.

Les deux obtiendront des éléments qui prennent de la place sur la page. Cela inclut les éléments avec le visibility: hidden propriété.

jsfiddle montrant cela en action.

3
Undefined