Heim > Artikel > Web-Frontend > Analyse der Init-Parameter des jQuery-Konstruktors Fortsetzung_jquery
Wenn der Selektor eine andere Zeichenfolge ist, wird die Situation komplizierter
// Handle HTML strings if ( typeof selector === "string" ) {...}
Beginnen Sie, mit unterschiedlichen Situationen umzugehen
// 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 ); }
Wenn zunächst festgestellt wird, dass das erste Zeichen „c6713c1c1dddf690bc89a2cec08c2031“ ist und die Länge größer als 3 ist, wird angenommen, dass es sich zu diesem Zeitpunkt um ein einfaches HTML-Tag handelt als $('dc6dce4a544fdca2df29d5ac0ea9906b'), aber denken Sie daran, einfach davon auszugehen, dass hier ein „assume“ wie $('d0a5801618bdd08d8316acfb7836b840') eingefügt wird. Ändern Sie dann das Übereinstimmungsarray in [null, Selektor, null]. Die Übereinstimmung wird hier hauptsächlich als Werkzeug zur Unterscheidung von Parametertypen verwendet Quellcode. Vier Variablen deklariert
init: function( selector, context, rootjQuery ) { var match, elem, ret, doc;
Wenn die if-Bedingung nicht erfüllt ist, wird ein regulärer Ausdruck aufgerufen, um das Übereinstimmungsergebnis zu erhalten. QuickExpr ist eine im jQuery-Konstruktor deklarierte Variable
// 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\-]*)$)/,
Diese reguläre Regel dient hauptsächlich der Unterscheidung von HTML-Strings und ID-Strings. Um XSS-Angriffe basierend auf location.hash zu vermeiden, wird # (#9521) zu quickExpr hinzugefügt, was bedeutet, dass wir Verwandte Erklärungen sein können gefunden auf der offiziellen jQuery-Website.
Besuchen Sie zuerst http://bugs.jquery.com/ und suchen Sie dann nach dem entsprechenden Wert
Das Ausführungsergebnis von quickExpr.exec(selector) kann ein Array sein. Das erste Element des Arrays ist das passende Element, und die restlichen Elemente sind gruppierte passende Elemente. Dieser reguläre Ausdruck hat zwei Gruppen (d4f5e2ddbd47324b300b03c84bc62ab7)[^>] und ([w-]*) sind Labels und ID-Werte. Das Ergebnis wird schließlich passend ausgegeben. Lassen Sie uns die verschiedenen Übereinstimmungssituationen analysieren. Zunächst hat ein einzelnes Label ohne regulären Ausdruck die Form [null, selector, null], was im folgenden Code bewiesen wird:
<!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>
In HTML erstellen wir ein jQuery-Objekt und geben dann das Übereinstimmungsergebnis in der Init-Methode aus:
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];
Ändern wir die Parameter in $(‘#div’) und schauen uns dann die Ergebnisse an
Es gibt auch einen Sonderfall $(‘dc6dce4a544fdca2df29d5ac0ea9906b123') und dann schauen wir uns das Ergebnis an
Wir können sehen, dass sich die ID immer im dritten Element befindet und der Tag-Wert im zweiten Element gespeichert wird. Im letzten Fall gibt es keinen Unterschied zu $('dc6dce4a544fdca2df29d5ac0ea9906b'), da es bei der Verwendung generiert wird Bei dom-Elementen wird das erste Element nicht verarbeitet. Basierend auf diesem Ergebnis können wir mit der Analyse des nächsten Urteils fortfahren.
Das Folgende wird basierend auf den Spielergebnissen in drei Situationen unterteilt
if ( match && (match[1] || !context) ) { ... } else if ( !context || context.jquery ) { ... } else { ... }
Die Bedingung, die im ersten Fall erfüllt ist, ist, dass match einen Wert haben muss. Match[1] bedeutet, dass das zweite Element dasjenige ist, das die Bezeichnung speichert. Es hat einen Wert oder hat keinen Kontext, aber es Es scheint, dass es keinen Ausweis gibt. Was ist los? Tatsächlich ist dies nicht der Fall. Durch die Analyse der Übereinstimmungsergebnisse können wir erkennen, dass das zweite Element ohne Wert das vom ID-Selektor erhaltene Ergebnis sein muss und die ID eindeutig ist und kein Kontext geschrieben werden muss (Tatsächlich wird der Kontext normal ausgeführt, wenn er geschrieben wird, aber stattdessen wird Sizzle verwendet. Er wird hier nicht auf die gleiche Weise wie der Text verarbeitet.) Okay, die erste Bedingung ist
1. Tag
$(‘dc6dce4a544fdca2df29d5ac0ea9906b') $(‘dc6dce4a544fdca2df29d5ac0ea9906b123') $(‘dc6dce4a544fdca2df29d5ac0ea9906b2321321316b28748ea4df4d9c2150843fecfba68')...
2. ID ohne Kontext $(‘#div’)
Die erste Bedingung ist intern weiter unterteilt:
// HANDLE: $(html) -> $(array) if ( match[1] ) { ... // HANDLE: $("#id") }else{ }
Natürlich wird es zur Verarbeitung von Tags und sonst zur Verarbeitung von IDs verwendet. Schauen wir uns zunächst an, wie Tags verarbeitet werden
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);
Korrigieren Sie zuerst den Wert des Kontexts, indem Sie ihn mithilfe der Subscript-Methode in ein DOM-Element umwandeln. Wenn der Kontext nicht vorhanden ist, wird er verarbeitet. Weisen Sie dem Dokument den Dokumentwert zu. Wenn es vorhanden ist und über das Attribut „ownerDocument“ verfügt, ist dieser Wert immer noch ein Dokument Variable. Unmittelbar danach wurde eine weitere reguläre Beurteilung des Selektors durchgeführt. Diese reguläre Regel wurde auch im jQuery-Konstruktor deklariert, um einzelne Tags wie dc6dce4a544fdca2df29d5ac0ea9906b zu beurteilen
然后把结果交给ret变量,基于ret的值又进行划分按照单标签和复杂标签分开处理ret值存在那就是匹配到了单标签然后再根据context是不是普通对象又分为两种情况isPlainObject是检测是不是普通对象的方法,如果是普通对象,就利用js原生方法createElement传入标签创建元素并放在一个数组里面,之所以这样是为了以后跟jquery对象合并方便,然后把数组赋值给selector,后采用对象冒充的方法调用attr方法,这里attr居然有3个参数,而平常我们使用的api里面是两个参数,其实jQuery中有很多类似的情况,同样的方法有着对内对外两个接口。第二个参数就是对象形式的上下文,因为attr可以像
这给我们的其实就是我们以后可以$(‘dc6dce4a544fdca2df29d5ac0ea9906b',{id:'div'})这样写了也是支持的。如果不是对象就直接创建元素不考虑属性。还是把创建的元素放在数组里面。如果ret没有值那就是复杂的标签了比如$(‘dc6dce4a544fdca2df29d5ac0ea9906b23116b28748ea4df4d9c2150843fecfba68')这样的这个时候原生的js就搞不定啦需要调取另外一个方法jQuery.buildFragment来处理,这个方法实现以后在学习吧,总之最后都会创建dom元素。最后返回合并后的结果
不像之前的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方法。
以上所述就是本文的全部内容了,希望大家能够喜欢。