Je veux savoir quelle est la différence entre querySelector
et querySelectorAll
et getElementsByClassName
code> Quelle est la différence ?
À partir de ce lien, j'ai appris qu'en utilisant querySelector
, je peux écrire document.querySelector(".myclass")
;code>myclass et document.querySelector("#myid")
pour obtenir l'élément avec l'ID myid
. Mais je peux déjà obtenir cette fonctionnalité en utilisant getElementsByClassName
et getElementById
. Lequel faut-il privilégier ?
De plus, je travaille dans XPages et les identifiants sont générés dynamiquement, contiennent des deux-points et ressemblent à ceci view:_id1:inputText1
. Donc, quand j'écris document.querySelector("#view:_id1:inputText1")
, ça ne marche pas. Mais quand j'écris document.getElementById("view:_id1:inputText1")
, ça marche. Avez-vous une idée de la raison pour laquelle cela se produit ?
Pour cette réponse, j'appellerai
querySelector
和querySelectorAll
称为querySelector*,将getElementById
、getElementsByClassName
、getElementsByTagName
和getElementsByName
getElement*.Une grande partie de ces informations peuvent être vérifiées dans la spécification, et une grande partie est dérivée de divers benchmarks que j'ai exécutés lors de l'écriture. Spécification :https://dom.spec.whatwg.org/
Principales différences
querySelector
和getElementById
都返回单个元素。querySelectorAll
和getElementsByName
都返回NodeList。getElementsByClassName
和getElementsByTagName
Les deux renvoient HTMLCollection. NodeList et HTMLCollection sont appelés des collections d'éléments.Ces notions sont résumées dans le tableau ci-dessous.
Détails, conseils et exemples
HTMLCollection ne ressemble pas à un tableau comme NodeList et ne prend pas en charge .forEach(). J'ai trouvé l'opérateur spread utile pour contourner ce problème :
[...document.getElementsByClassName("someClass")].forEach()
implémenté sur chaque élément et globalement
document
都可以访问所有这些函数,除了getElementById
和getElementsByName
,它们只在document
.Chaîner les appels getElement* au lieu de querySelector* améliorera les performances, en particulier sur les très grands DOM. Généralement plus rapide même sur les petits DOM et/ou les très longues chaînes. Cependant, la lisibilité de querySelector* doit être préférée à la lisibilité, sauf si vous savez que vous avez besoin de performances.
querySelectorAll
Habituellement plus difficile à remplacer car vous devez sélectionner des éléments dans une NodeList ou une HTMLCollection à chaque étape. Par exemple, le code suivantne fonctionne pas:document.getElementsByClassName("someClass").getElementsByTagName("div")
Parce que vous ne pouvez utiliser getElements* que sur un seul élément, pas sur une collection, mais si vous ne voulez qu'un seul élément alors :
document.querySelector("#someId .someClass div")
peut s'écrire :
document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]
Notez la même utilisation de
[0]
,以获取集合的第一个元素,最终结果只有一个元素,就像使用querySelector
à chaque étape du retour de la collection.Étant donné que tous les éléments peuvent être appelés à l'aide de querySelector* et getElement*, il est possible d'enchaîner les opérations en utilisant les deux appels, ce qui est très utile lorsque vous souhaitez des gains de performances mais que vous ne pouvez pas éviter d'utiliser un querySelector qui ne peut pas être écrit avec getElement* l'appelle travaux.
Bien qu'il soit généralement facile de savoir si un sélecteur peut être écrit en utilisant uniquement des appels getElement*, il existe un cas où cela peut ne pas être évident :
document.querySelectorAll(".class1.class2")
peut être réécrit comme
document.getElementsByClassName("class1 class2")
L'utilisation de getElement* sur un élément statique obtenu avec querySelector* rendra l'élément dynamique par rapport au sous-ensemble statique du DOM copié par querySelector, mais statique par rapport au DOM complet du document... c'est ce que sont les éléments dynamiques/statiques simples. Voici où l’explication commence à s’effondrer. Vous devriez essayer d'éviter les situations où vous devez vous en soucier, mais si cela existe, rappelez-vous que les appels querySelector* copient les éléments qu'ils trouvent avant de renvoyer la référence, tandis que les appels getElement* obtiennent la référence directement sans copier.
querySelector* et
getElementById
以前序、深度优先的方式遍历元素,在规范中称为“树顺序”。对于其他getElement*调用,从规范中我无法确定它们是否与树顺序相同,但getElementsByClassName(".someClass")[0]
可能在每个浏览器中结果不可靠。getElementById("#someId")
devraient être fiables même si vous avez plusieurs copies du même identifiant sur votre page.J'ai dû examiner ce problème lorsque je travaillais sur une page à défilement infini et j'ai pensé que cela pourrait être une situation courante où les performances deviennent un problème. Nous avons l'événement onScroll dans notre code qui contient l'appel querySelectorAll. Même si les appels sont limités en débit, la page plantera si vous faites défiler suffisamment loin, auquel cas il y aura trop d'appels itérant sur trop d'éléments pour que le navigateur puisse suivre. La taille du DOM est pertinente dans ce cas d'utilisation, donc dans le code exécuté sur une page à défilement infini, les appels getElement* sont préférés.
Prise en charge de la syntaxe et du navigateur.
querySelector
Plus utile lorsque vous souhaitez utiliser des sélecteurs plus complexes.Par exemple, une liste de tous les éléments appartenant à la classe foo :
Les caractères.foo li
:
ont une signification particulière dans les sélecteurs. Il faut y échapper. (Le caractère d'échappement du sélecteur a également une signification particulière dans les chaînes JS, vous devez donc également échapperit).