Maison  >  Article  >  interface Web  >  Interprétation du code source du sélecteur jQuery (8) : addCombinator function_jquery

Interprétation du code source du sélecteur jQuery (8) : addCombinator function_jquery

WBOY
WBOYoriginal
2016-05-16 16:06:541023parcourir

fonction addCombinator(matcher, combinator, base)

1、源码

复制代码 代码如下 :

function addCombinator(matcher, combinator, base) {
 var dir = combinator.dir, checkNonElements = base
   && dir === "parentNode", doneName = done ;

 return combinator.first ?
 // Vérification par rapport à l'ancêtre/élément précédent le plus proche
 fonction (elem, contexte, xml) {
  while ((elem = elem[dir])) {
   if (elem.nodeType === 1 || checkNonElements) {
    return matcher(elem, contexte, xml);
   >
  >
 } :

 // Vérifier par rapport à tous les éléments ancêtres/précédents
 fonction (elem, contexte, xml) {
  var data, cache, externalCache, dirkey = dirruns " " doneName;

  // Nous ne pouvons pas définir de données arbitraires sur les nœuds XML, donc ils ne le font pas
  // bénéficier de la mise en cache du répertoire
  si (xml) {
   while ((elem = elem[dir])) {
    if (elem.nodeType === 1 || checkNonElements) {
     if (matcher(elem, contexte, xml)) {
      renvoie vrai ;
     >
    >
   >
  } autre {
   while ((elem = elem[dir])) {
    if (elem.nodeType === 1 || checkNonElements) {
     externalCache = elem[expando] || (elem[expando] = {});
     si ((cache = externalCache[dir])
       && cache[0] === répertoire) {
      if ((data = cache[1]) === true
        || data === cachedruns) {
       renvoyer les données === vrai ;
      >
     } autre {
      cache = externalCache[dir] = [ dirkey ];
      cache[1] = matcher(elem, contexte, xml)
        || cachedruns;
      if (cache[1] === vrai) {
       renvoie vrai ;
      >
     >
    >
   >
  >
 };
>

2、功能

生成关系选择器的执行函数。

3、参数

matcher——是否符合选择器要求。在实际执行过程中,该函数可能是关系选择器前已Il s'agit d'elementMatcher(matchers)。例如:div.map>span,et Sizzle编译遇到>时,会将div.map的编译函数作为第一个参数调用addCombinator函数, 以检查获取的span父节点是否满足div.map这两个条件。

combinateur——关系选择器对应Expr.relative中的值,Expr.relative中各种关系选择器的值如下。使用该参数的first属性来确定返回的是仅检查紧邻对象的函数还是遍历所有Description du produit

复制代码 代码如下 :
Expr.relatif : {
 ">" : {
  rép : "parentNode",
  premier : vrai
 },
 " : {
  rép : "parentNode"
 },
 " : {
  dir : "précédentSibling",
  premier : vrai
 },
 "~" : {
  dir : "précédentSibling"
 >
>

base - Ce paramètre, avec combinator.dir, détermine la valeur de la variable checkNonElement. Le code est le suivant. Cette valeur signifie littéralement que la vérification actuelle est un élément non-DOM, c'est-à-dire que lorsque elem.nodeType!=1, si la valeur est vraie, la fonction correspondante sera exécutée, sinon la boucle se terminera.

4. Fonction de retour

4.1 Si le sélecteur de relation est > ou , la fonction suivante est renvoyée :

Copier le code Le code est le suivant :

fonction (elem, contexte, xml) {
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
Retour matcher(elem, contexte, xml);
>
>
>

4.1.1 Fonction
Si le nœud de type d'élément est vérifié (c'est-à-dire checkNonElements==false), obtenez de manière itérative le premier nœud de type d'élément de la relation de position spécifiée par elem (elem.nodeType == 1), exécutez la fonction de correspondance, vérifiez si le nœud répond aux exigences, et renvoie true s'il répond aux exigences, sinon renvoie false

.

Si tous les types de nœuds sont vérifiés (c'est-à-dire checkNonElements==true), obtenez les nœuds adjacents avec la relation de position spécifiée d'elem, exécutez la fonction de correspondance, vérifiez si le nœud répond aux exigences, retournez true s'il répond aux exigences , sinon renvoie false
Certains se demanderont peut-être : ne dit-on pas qu'il s'agit d'une relation de voisinage étroit ? Alors pourquoi le processus d’acquisition itérative apparaît-il dans le code ? En effet, certains navigateurs considéreront les sauts de ligne entre les textes des nœuds comme TextNode, donc pendant le traitement, ces nœuds doivent être ignorés jusqu'au nœud d'élément suivant.
4.1.2 Paramètres
elem – l’élément de nœud unique à vérifier.

context - le nœud de contexte qui effectue la correspondance complète de la chaîne de sélection, la plupart du temps, il est inutile.

xml——L'objet de recherche actuel est-il un document HTML ou XML ? S'il s'agit de HTML, le paramètre xml est faux.

4.2 Si le sélecteur de relation est ~ ou espace, la fonction suivante sera renvoyée :

Copier le code Le code est le suivant :

//Vérifier tous les éléments ancêtres/précédents
fonction (elem, contexte, xml) {
var data, cache, externalCache, dirkey = dirruns " " doneName;

// Nous ne pouvons pas définir de données arbitraires sur les nœuds XML, donc ils ne le font pas
// bénéficier de la mise en cache du répertoire
si (xml) {
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
Si (matcher(elem, contexte, xml)) {
Renvoie vrai ;
>
>
>
} autre {
while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
externalCache = elem[expando] || (elem[expando] = {});
Si ((cache = externalCache[dir])
&& cache[0] === répertoire) {
Si ((data = cache[1]) === true
|| data === cachedruns) {
        renvoie des données === vrai ;
>
} autre {
cache = externalCache[dir] = [dirkey];
cache[1] = matcher(elem, contexte, xml)
|| exécutions en cache ;
Si (cache[1] === vrai) {
        return true ;
>
>
>
>
>
};

4.2.1 Fonction

Si vous vérifiez un document XML, le processus est le même que la fonction de retour dans 4.1. Voir le code entre accolades dans if (XML) { ... } dans le code ci-dessus.

S'il s'agit d'un document HTML, faites correspondre l'élément actuel en fonction du matcher. Si la correspondance est réussie, renvoyez true sinon, renvoyez false.

4.2.2 Paramètres
elem – l’élément de nœud unique à vérifier.

context - le nœud de contexte qui effectue la correspondance complète de la chaîne de sélection, la plupart du temps, il est inutile.

xml——L'objet de recherche actuel est-il un document HTML ou XML ? S'il s'agit de HTML, le paramètre xml est faux.

4.2.3 Description du code

Variables internes

dirkey - la clé utilisée pour mettre en cache les résultats de détection des nœuds. Lors d'une exécution, si un nœud est vérifié, le résultat de la détection (vrai ou faux) sera enregistré dans l'attribut dirkey du nœud (le nom de l'attribut est la valeur de dirkey puis lors de cette exécution, s'il est rencontré à nouveau en atteignant celui-ci). nœud, il n’est pas nécessaire de le détecter à nouveau. La raison pour laquelle la mise en cache est nécessaire est que plusieurs nœuds auront le même nœud parent ou frère. L'utilisation de la mise en cache peut réduire le nombre de détections et améliorer les performances.

dirruns - Chaque fois que le code précompilé organisé par matcherFromGroupMatchers est exécuté, un nombre pseudo-aléatoire sera généré pour distinguer les différents processus d'exécution.
doneName——Chaque fois que la fonction addCombinator est exécutée, la variable done sera incrémentée de 1 pour distinguer les différentes fonctions de correspondance de relation de position générées.

cachedruns - utilisé pour enregistrer à quel élément DOM correspond cette correspondance. Par exemple : div.map>span, il y a 3 éléments qui correspondent au sélecteur de durée, puis lorsque la fonction de correspondance > est exécutée pour chaque élément, les mises en cache sont 0, 1 et 2 dans l'ordre. Selon le code, le rôle des cachedruns peut être directement compris car lors d'un processus d'exécution, lors de l'utilisation d'elementMatchers pour le même élément pour la correspondance, lorsque le même élément est rencontré à nouveau, le résultat sans correspondance peut être obtenu directement à partir de C'est ce qui se passe. Si quelqu'un le rencontre, n'hésitez pas à me le faire savoir, merci !

Explication du code

Copier le code Le code est le suivant :

while ((elem = elem[dir])) {
if (elem.nodeType === 1 || checkNonElements) {
// Si l'attribut expando du nœud elem n'existe pas, donnez-lui un objet vide et donnez-le à externalCache
en même temps. // Si l'attribut expando du nœud elem existe, attribuez sa valeur à externalCache
externalCache = elem[expando] || (elem[expando] = {});
/*
* Si outCache[dir] a une valeur et que son premier élément est égal au répertoire actuel,
* Cela signifie que le sélecteur de position actuelle a détecté le nœud lors de cette exécution, exécuté l'instruction dans le if et obtenu le résultat directement depuis le cache
* Si outCache[dir] n'existe pas, ou si le premier élément n'est pas égal au répertoire actuel,
* * Cela signifie que le sélecteur de position actuelle n'a pas détecté le nœud lors de cette exécution, exécute l'instruction dans else, fait correspondre le nœud et met le résultat dans le cache
*/
si ((cache = externalCache[dir])
&& cache[0] === répertoire) {
// Si le résultat de la détection dans le cache est égal à vrai ou à la valeur de cachedruns, le résultat de la détection sera renvoyé (soit faux, soit vrai),
// Sinon, continuez la boucle pour obtenir le nœud précédent qui correspond à la relation de position pour la correspondance
if ((data = cache[1]) === true
|| data === cachedruns) {
Données de retour === vrai ;
>
} autre {
//Attribuez le tableau [dirkey] à externalCache[dir] et au cache
cache = externalCache[dir] = [ dirkey ];
// Si la correspondance réussit, attribuez true au cache[1], sinon attribuez la valeur de cachedruns au cache[1]
cache[1] = matcher(elem, contexte, xml)
|| exécutions en cache ;
// Si le résultat de la correspondance est vrai, renvoie vrai, sinon continuez la boucle pour obtenir le nœud précédent qui correspond à la relation de position pour la correspondance
if (cache[1] === vrai) {
Renvoie vrai ;
>
>
>
>
Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn