Jika pemilih adalah rentetan lain, keadaan akan menjadi lebih rumit
// Handle HTML strings if ( typeof selector === "string" ) {...}
Mula menangani situasi yang berbeza
// 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 ); }
Jika pertama kali dinilai bahawa aksara pertama ialah "<" dan aksara terakhir ialah ">" dan panjangnya lebih besar daripada 3, diandaikan bahawa pemilih pada masa ini ialah teg html yang mudah, seperti sebagai $('
init: function( selector, context, rootjQuery ) { var match, elem, ret, doc;
Jika syarat if tidak dipenuhi, ungkapan biasa akan dipanggil untuk mendapatkan hasil padanan quickExpr ialah pembolehubah yang diisytiharkan dalam pembina 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\-]*)$)/,
Peraturan biasa ini terutamanya untuk membezakan rentetan html dan rentetan id Komen kedua menyebut bahawa untuk mengelakkan serangan XSS berdasarkan location.hash, # (#9521) ditambahkan pada quickExpr, yang bermaksud kami Penjelasan berkaitan boleh dibuat. ditemui di laman web rasmi jQuery.
Lawatan pertama http://bugs.jquery.com/ dan kemudian cari nilai yang sepadan
Hasil pelaksanaan quickExpr.exec(pemilih) boleh menjadi tatasusunan Elemen pertama tatasusunan ialah elemen padanan, dan elemen yang selebihnya ialah elemen padanan berkumpulan ini mempunyai dua kumpulan (<[wW] >)[^>] dan ([w-]*) ialah label dan nilai id. Keputusan akhirnya akan diberikan padan. Mari analisa pelbagai situasi padanan Pertama, satu label tanpa ungkapan biasa adalah dalam bentuk [null, selector, null], yang dibuktikan dalam kod di bawah:
<!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>
Dalam html kami mencipta objek jQuery dan kemudian mengeluarkan hasil padanan dalam kaedah 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];
Mari ubah suai parameter kepada $(‘#div’) dan kemudian lihat hasilnya
Terdapat juga kes khas $(‘
Kita dapat melihat bahawa id sentiasa berada dalam elemen ketiga dan nilai teg disimpan dalam elemen kedua Untuk kes terakhir, tiada perbezaan daripada $('
Berikut akan dibahagikan kepada tiga situasi berdasarkan keputusan perlawanan
if ( match && (match[1] || !context) ) { ... } else if ( !context || context.jquery ) { ... } else { ... }
Syarat yang dipenuhi dalam kes pertama ialah padanan mesti mempunyai nilai Padanan[1] bermakna elemen kedua ialah elemen yang menyimpan label itu mempunyai nilai atau tidak mempunyai konteks nampaknya tiada ID. Sebenarnya, ini tidak berlaku Dengan menganalisis keputusan padanan, kita dapat mengetahui bahawa elemen kedua tanpa nilai mestilah hasil yang diperolehi oleh pemilih id, dan id adalah unik, dan tidak perlu menulis konteks. (sebenarnya, jika konteks ditulis, ia akan dilaksanakan seperti biasa, tetapi Sizzle akan digunakan sebaliknya. Ia tidak diproses di sini sama seperti badan). Okay, syarat pertama yang masuk ialah
1. Tag
$(‘
2 ID tanpa konteks $(‘#div’)
Syarat pertama dibahagikan lagi secara dalaman:
// HANDLE: $(html) -> $(array) if ( match[1] ) { ... // HANDLE: $("#id") }else{ }
Jelas sekali jika digunakan untuk memproses teg dan sebaliknya digunakan untuk memproses id Mari kita lihat dahulu cara teg diproses
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);
Pertama-tama betulkan nilai konteks Jika ia adalah objek jQuery, ubahnya menjadi elemen dom menggunakan kaedah subskrip ini telah disebut sebelum ini, dan kemudian pembolehubah doc diproses. tetapkan nilai dokumen kepada doc Jika ia wujud dan mempunyai atribut ownerDocument, ia adalah elemen dom Jika ia bukan elemen dom, seperti objek js biasa, maka tetapkan objek ini kepada doc pembolehubah. Sejurus selepas itu, satu lagi penghakiman biasa telah dilakukan pada pemilih peraturan biasa ini juga diisytiharkan dalam pembina jQuery untuk tujuan menilai teg tunggal, seperti
然后把结果交给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方法。
以上所述就是本文的全部内容了,希望大家能够喜欢。