Si le sélecteur est une autre chaîne, la situation sera plus compliquée
// Handle HTML strings if ( typeof selector === "string" ) {...}
Commencez à gérer différentes situations
// Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); }
S'il est d'abord jugé que le premier caractère est "<" et que le dernier caractère est ">" et que la longueur est supérieure à 3, on suppose que le sélecteur à ce moment est une simple balise html, telle comme $('
init: function( selector, context, rootjQuery ) { var match, elem, ret, doc;
Si la condition if n'est pas remplie, une expression régulière sera appelée pour obtenir le résultat de la correspondance. quickExpr est une variable déclarée dans le constructeur jQuery
.// A simple way to check for HTML strings or ID strings // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
Cette règle habituelle sert principalement à distinguer les chaînes html et les chaînes d'identification. Le deuxième commentaire mentionne que afin d'éviter les attaques XSS basées sur location.hash, # (#9521) est ajouté à quickExpr, ce qui signifie que nous pouvons avoir des explications associées. trouvé sur le site officiel de jQuery.
Visitez d'abord http://bugs.jquery.com/ puis recherchez la valeur correspondante
Le résultat de l'exécution de quickExpr.exec(selector) peut être un tableau. Le premier élément du tableau est l'élément correspondant, et les éléments restants sont des éléments correspondants regroupés. Cette expression régulière comporte deux groupes (<[wW] >)[^>] et ([w-]*) sont des étiquettes et des valeurs d'identification. Le résultat sera finalement donné à la hauteur. Analysons les différentes situations de correspondance. Tout d'abord, une seule étiquette sans expression régulière se présente sous la forme de [null, selector, null], ce qui est prouvé dans le code ci-dessous :
<!doctype html> <html> <head> <title></title> <script src='jquery-1.7.1.js'></script> </head> <body> <div id='div'></div> </body> <script> $('<div>'); </script> </html>
En HTML, nous créons un objet jQuery puis affichons le résultat de la correspondance dans la méthode init :
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } console.log(match); // [null, "<div>", null];
Modifions les paramètres en $('#div') puis jetons un œil aux résultats
Il existe aussi un cas particulier $('
Nous pouvons voir que l'identifiant est toujours dans le troisième élément et que la valeur de la balise est enregistrée dans le deuxième élément. Pour le dernier cas, il n'y a pas de différence avec $('
Ce qui suit sera divisé en trois situations en fonction des résultats du match
if ( match && (match[1] || !context) ) { ... } else if ( !context || context.jquery ) { ... } else { ... }
La condition remplie dans le premier cas est que match doit avoir une valeur. Match[1] signifie que le deuxième élément est celui qui enregistre l'étiquette. Il a une valeur ou n'a pas de contexte, mais il. il semble qu'il n'y ait pas de pièce d'identité. Quel est le problème ? En fait, ce n'est pas le cas. En analysant les résultats de la correspondance, on peut savoir que le deuxième élément sans valeur doit être le résultat obtenu par le sélecteur d'identifiant, et l'identifiant est unique, et il n'est pas nécessaire d'écrire un contexte. (en fait, si le contexte est écrit, il s'exécutera normalement, mais Sizzle sera utilisé à la place. Il n'est pas traité ici de la même manière que le corps). D'accord, la première condition qui entre en jeu est
1.Étiquette
$('
2. ID sans contexte $('#div')
La première condition est subdivisée en interne :
// HANDLE: $(html) -> $(array) if ( match[1] ) { ... // HANDLE: $("#id") }else{ }
Évidemment, if est utilisé pour traiter les balises et else est utilisé pour traiter les identifiants. Voyons d'abord comment les balises sont traitées
.
context = context instanceof jQuery ? context[0] : context; doc = ( context ? context.ownerDocument || context : document ); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; } return jQuery.merge( this, selector);
Corrigez d'abord la valeur du contexte. S'il s'agit d'un objet jQuery, transformez-le en élément dom en utilisant la méthode de l'indice. Ce principe a été mentionné précédemment, puis la variable doc est traitée. attribuez la valeur du document à doc. S'il existe et possède l'attributownerDocument, il s'agit d'un élément dom. S'il ne s'agit pas d'un élément dom, tel qu'un objet js ordinaire, attribuez cet objet au doc. variable. Immédiatement après, un autre jugement régulier a été effectué sur le sélecteur. Cette règle régulière a également été déclarée dans le constructeur jQuery dans le but de juger des balises uniques, telles que
然后把结果交给ret变量,基于ret的值又进行划分按照单标签和复杂标签分开处理ret值存在那就是匹配到了单标签然后再根据context是不是普通对象又分为两种情况isPlainObject是检测是不是普通对象的方法,如果是普通对象,就利用js原生方法createElement传入标签创建元素并放在一个数组里面,之所以这样是为了以后跟jquery对象合并方便,然后把数组赋值给selector,后采用对象冒充的方法调用attr方法,这里attr居然有3个参数,而平常我们使用的api里面是两个参数,其实jQuery中有很多类似的情况,同样的方法有着对内对外两个接口。第二个参数就是对象形式的上下文,因为attr可以像
这给我们的其实就是我们以后可以$(‘
不像之前的return this这里是返回merge执行后的结果其实他的任务就是把放在数组里面的创建好的的dom元素合并到jquery元素中去,最终变成{0:div,length:1...}这样的对象形式。这样的话简标签情况就处理完毕。
然后else里面处理的是id的情况
elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this;
很简单直接调用原生js的id选择器但是有一些系统会出现bug
注释说的很清楚黑莓系统,就是元素已经不存在了但是依然能够匹配得到所以再加上父节点,不存在的元素肯定没有父节点的。还有一种情况就是ie和opera浏览器会出现按name值匹配的情况所以在做了一个判断
if ( elem.id !== match[2] ) {
如果真的不幸出现了那就不能使用原生方法而是用find方法也就是使用sizzle引擎了,在大多数正常情况下就直接将获取到的元素放到this里面就可以啦然后修改下context的值。Ok终于把第一个大分支分析完了。然后再看根据match的第二个分支
else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); }
这里是如果没有上下文或者上下文是jquery对象的时候这个比较简单就是直接用find方法了rootjQuery 就是$(document)
最后字符串的情况上面都不属于的话
This.constructor就是jQuery其实还是使用find方法。
以上所述就是本文的全部内容了,希望大家能够喜欢。