ホームページ >ウェブフロントエンド >jsチュートリアル >Jquery 1.9.1 ソース コード分析シリーズのフィルタリング操作
早速、本題に入りましょう。
jQuery.fn.find( selector )
find は、パラメーター式セレクター: セレクター (文字列)、DOM 要素 (Element)、jQuery オブジェクトを受け入れます。これは 2 つの状況で処理されます。
最初の状況では、受信パラメーターが文字列以外の場合、まず jQuery セレクターを通じてセレクターを見つけ、次に現在のパラメーターに含まれる一致する項目をフィルターで除外します。 jQuery オブジェクト。
if ( typeof selector !== "string" ) { self = this; return this.pushStack( jQuery( selector ).filter(function() { for ( i = 0; i < len; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }) ); }
この関数は、フィルター条件のキーとして jQuery.contains( self[ i ], this ) が使用されていることがわかります。 Sizzle エンジンには分析があります。詳細については、クリックしてください。
次に、セレクターが文字列の場合、jQuery.find (= Sizzle) を呼び出して直接処理します。
ret = []; for ( i = 0; i < len; i++ ) { //第二个参数是表示context jQuery.find( selector, this[ i ], ret ); } //$( selector, context )变成$( context ).find( selector ),需要去重和pushStack ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; return ret;
jQuery.fn.closest( selectors, context )
2 番目のパラメータはオプションです。この関数は、現在一致している要素から開始して、指定された式に一致する最初の要素を選択するために使用され、それを jQuery オブジェクトの形式で返します。
ここでの式には、セレクター (文字列)、DOM 要素 (Element)、および jQuery オブジェクトが含まれます。
コード内の処理手順は
1. まず、渡されたパラメーターに従って結果をクエリし、pos に保存します。
pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0;
2. この要素から開始して、現在の jQuery オブジェクトの各要素をたどって、指定された式に一致する最初の祖先要素を段階的に選択します。
for ( ; i < l; i++ ) { cur = this[i]; while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } cur = cur.parentNode; } } return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
parents() メソッドと .closest() メソッドは、両方とも DOM ツリーを上に移動するという点で似ています。しかし、違いも非常に大きく、最も近いものは条件を満たす最初のセットを見つけて、親は条件を満たすすべてのセットを見つけます。
jQuery.fn.parent/parents/parentsUntil/next/prev/nextAll/prevAll/nextUntil/prevUntil/兄弟/子/内容詳細説明
上記のグループのフィルタがまとめて処理され、ソース コードは次のとおりです。
jQuery.each({ parent: function( elem ) {…}, parents: function( elem ) {…}, parentsUntil: function( elem, i, until ) {…}, next: function( elem ) {…}, prev: function( elem ) {…}, nextAll: function( elem ) {…}, prevAll: function( elem ) {…}, nextUntil: function( elem, i, until ) {…}, prevUntil: function( elem, i, until ) {…}, siblings: function( elem ) {…}, children: function( elem ) {…}, contents: function( elem ) {…} }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); //过滤 ... return this.pushStack( ret ); }; });
これらのフィルタリング ステップは一貫していることがわかります。現在の jQuery オブジェクトの各一致要素は、まずマップ関数を通じて対応する一致関数 (fn) に代入されて結果が取得され、その後フィルタリングが実行されます。
最初に後続のフィルタリングを見てみましょう (代替シード ret は jQuery.map(this, fn, until ) を通じて取得されています)
まず第一に、すべてのフィルタリング関数がuntil このパラメーターは、Until で終わるいくつかのフィルターにのみ必要です。他のフィルターにはセレクター パラメーターのみがあります。
if ( !runtil.test( name ) ) { selector = until; }
次に、セレクターがある場合は、セレクター ret を通じて前の検索結果をフィルターします。
if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); }
その後、保証された eedUniqueいくつかのフィルタリング条件 (children/contents/next/prev) がある場合、現在の jQuery オブジェクトに一致する要素の数が複数ある場合、各一致要素によって得られた結果は結果セット ret に保存されるため、重みを削除する必要はありません。 。他のスクリーニングを行う必要があります。クリックすると、jQuery.unique メソッドの詳細な説明が表示されます
ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
さらに、処理する必要がある特殊なケースは次のとおりです。 現在の jQuery と一致する要素が複数ある場合オブジェクト、親を使用 /prevUntil / prevAll これら 3 つのフィルターの結果は、逆順に並べ替える必要があります。逆の順序が必要な理由: jQuery.unique は、Sizzle エンジンの並べ替え関数 Sizzle .uniqueSort を使用し、ドキュメント内のオブジェクトを最上位のオブジェクトから最下位のオブジェクトに配置します。
if ( this.length > 1 && rparentsprev.test( name ) ) { ret = ret.reverse(); }
最後に、パッケージ化された結果を返します
return this.pushStack( ret );
上記はテーマのフレームワーク構造について説明しました。グループ フィルター マッチング関数で使用される 2 つの関数 jQuery.dir と jQuery.sibling については、ソース コードに直接移動します
// 現在の要素 elem で指定された dir に対応するノードから dir を検索し、これらのノードを保存しますループが終了するまで in が一致します。 注: 結果には elem ノードは含まれません
dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, //获取节点n及其兄弟节点中非elem的节点集合r sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } //找到当前元素cur的下一个dir为止 function sibling( cur, dir ) { do { cur = cur[ dir ]; } while ( cur && cur.nodeType !== 1 ); return cur; }
jQuery.fn.add( selector, context )和jQuery.fn. addBack( selector )
add 関数は、指定された式を現在の一致に追加します。 element 式の要素であり、jQuery オブジェクトとして返されます。 add は、セレクター (文字列)、HTML コンテンツ (文字列)、DOM 要素 (Element)、および jQuery オブジェクトを受け取ることができます。処理は比較的単純です。ソース コードに移動するだけです。
add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), //把selector表达式获取的结果集拼接到当前对象上 all = jQuery.merge( this.get(), set ); //返回新的拼接结果 return this.pushStack( jQuery.unique(all) ); } jQuery.fn.add和jQuery.fn.not相对应。jQuery.fn.not后面再说。 jQuery.fn.addBack将之前匹配的元素加入到当前匹配的元素中,并以新的jQuery对象的形式返回。 addBack: function( selector ) { return this.add( selector == null ? this.prevObject : this.prevObject.filter(selector) ); } jQuery.fn.andSelf = jQuery.fn.addBack; jQuery.fn.not( selector )和jQuery.fn.filter( selector ) not: function( selector ) { return this.pushStack( winnow(this, selector, false) ); } filter: function( selector ) { return this.pushStack( winnow(this, selector, true) ); },
not と filter はどちらも操作自体のコレクションであり、コレクション自体内の項目をフィルターで除外するものではありません。他の項目はそのままにして、フィルタリング条件セレクターを満たします。フィルターは、フィルター条件セレクターを満たす項目を残します。
鍵となるのは関数 winnow(elements, qualifier, keep) です。この関数の機能は、同じフィルタリング機能または非フィルタリング機能を実行することです。フィルター条件修飾子には、関数、DOM ノード、文字列の 3 種類があります。 keep: true はフィルター条件を満たす項目を保持することを意味し、false はフィルター条件を満たさない項目を保持することを意味します。
winnowのソースコードコメントは以下の通りです。
//执行相同的过滤或者不过滤的功能 function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; //如果过滤条件是函数,则通过过滤函数过滤 if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); //如果过滤条件是DOM相关类型,通过比较节点是否相同来过滤 } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem ) { return ( elem === qualifier ) === keep; }); //如果过滤条件是字符串 } else if ( typeof qualifier === "string" ) { //过滤出elements中的节点元素 var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); // 其中isSimple = /^.[^:#\[\.,]*$/ if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { //查找filtered中满足筛选条件qualifier的节点 qualifier = jQuery.filter( qualifier, filtered ); } } //过滤出elements中满足过滤条件的元素 return jQuery.grep(elements, function( elem ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; }); }
jQuery.grepを使用します。grepの詳しい説明はここをクリックしてください。
jQuery.filter(expr, elems, not) この低レベル API は、jQuery.fn.filter のフィルター条件が文字列である場合を処理するために特別に使用されます。
jQuery.filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } //其中matchesSelector和matches是Sizzle中的函数。matchesSelector是判断单个元素elem是否满足表达式expr,matches是查找元素集合elems中满足表达式expr的项 return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, jQuery.fn.index( elem )
index函数实际上是一个多功能函数的集合。
第一个功能:不传递elem参数,则表示取当前jQuery对象(jQuery对象的第一个元素)在其所有同辈元素中的位置。
if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; }
第二个功能:如果参数为String类型则将其视作选择器,返回当前元素在选择器所匹配的元素中的索引位置。如果该选择器不匹配任何元素或者当前元素不在匹配到的元素内,则返回-1。
if ( typeof elem === "string" ) { //在数组jQuery( elem )中搜索指定的值,并返回其索引值 return jQuery.inArray( this[0], jQuery( elem ) ); }
第三个功能:如果object为DOM元素或jQuery对象,则返回该元素(或该jQuery对象中的第一个元素)在当前jQuery对象所匹配的元素中的索引位置。
return jQuery.inArray(elem.jquery ? elem[0] : elem, this );
其他的筛选处理就不分析了。看源码即可明白。
【相关教程推荐】
1. JavaScript视频教程
2. JavaScript在线手册
3. bootstrap教程