ホームページ  >  記事  >  ウェブフロントエンド  >  jquery全体のアーキテクチャ分析と実装例を詳しく解説_jquery

jquery全体のアーキテクチャ分析と実装例を詳しく解説_jquery

WBOY
WBOYオリジナル
2016-05-16 16:31:571229ブラウズ

jQuery フレームワーク全体は非常に複雑で、理解するのが簡単ではありません。ここ数日間、この重く強力なフレームワークを研究してきました。 jQuery の全体的なアーキテクチャは、エントリ モジュール、ボトム モジュール、機能モジュールに分けることができます。ここでは jquery-1.7.1 を例として分析します。

jquery の全体的なアーキテクチャ

コードをコピーします コードは次のとおりです:

16 (関数(ウィンドウ, 未定義) {
// jQuery オブジェクトを構築します
22 var jQuery = (function() {
25 var jQuery = 関数(セレクター, コンテキスト) {
27 return new jQuery.fn.init(selector, context, rootjQuery);
28 },
// ローカル変数宣言の束
97 jQuery.fn = jQuery.prototype = {
98 コンストラクター: jQuery,
99 init: function(selector, context, rootjQuery) { ... },
// 一連のプロトタイプのプロパティとメソッド
319 };
322 jQuery.fn.init.prototype = jQuery.fn;
324 jQuery.extend = jQuery.fn.extend = function() { ... };
388 jQuery.extend({
// 一連の静的プロパティとメソッド
892 });
955 return jQuery;
957 })();
//他のモジュールのコードを省略...
9246 window.jQuery = window.$ = jQuery;
9266 })( ウィンドウ );

上記のコードを分析すると、jquery は匿名関数の自己実行という記述方法を採用しているため、名前空間と変数の汚染の問題を効果的に防ぐことができることがわかりました。上記のコードを省略すると次のようになります:

コードをコピーします コードは次のとおりです:

(関数(ウィンドウ、未定義) {
var jQuery = function() {}
// ...
window.jQuery = window.$ = jQuery;
})(ウィンドウ);

パラメータウィンドウ

匿名関数は 2 つのパラメーターを渡します。1 つはウィンドウ、もう 1 つは未定義です。 js の変数にはスコープ チェーンがあることがわかっています。渡された 2 つの変数は匿名関数のローカル変数になり、より高速にアクセスされます。ウィンドウオブジェクトを渡すことで、ウィンドウオブジェクトをローカル変数として使用できるようになり、jqueryでウィンドウオブジェクトにアクセスする際にスコープチェーンを先頭に戻す必要がなくなりました。 -level スコープなので、ウィンドウ オブジェクトにより速くアクセスできます。

パラメータが未定義

js が変数を検索するとき、js エンジンはまず関数自体のスコープ内で変数を検索し、変数が存在しない場合は上方向に検索を続けます。見つからない場合は、unknown が返されます。 unfineed は window オブジェクトのプロパティです。値を代入せずに unknown パラメータを渡すことにより、unknown を検索する際のスコープ チェーンを短くすることができます。自己呼び出し匿名関数のスコープ内では、未定義が本当に未定義であることを確認してください。未定義は上書きして新しい値を与えることができるためです。

jquery.fn とは何ですか?

コードをコピー コードは次のとおりです:

jQuery.fn = jQuery.prototype = {
コンストラクター: jQuery,
init: function(selector, context, rootjQuery) { ... },
// 一連のプロトタイプのプロパティとメソッド
};

上記のコードを分析すると、jQuery.fn は jQuery.prototype であることがわかりました。この方法で記述する利点は、コードが短いことです。その後、jquery では簡素化のために jquery の代わりに $ 記号が使用されていることがわかりました。そのため、jquery フレームワークを使用する場合は、$()、

を使用することがよくあります。

コンストラクター jQuery()

画像の説明

jQuery オブジェクトは新しい jQuery ではなく、新しい jQuery.fn.init を通じて作成されます。

コードをコピーします コードは次のとおりです:

var jQuery = function(セレクター, コンテキスト) {

return new jQuery.fn.init( selector, context, rootjQuery );

}

ここでは変数 jQuery が定義されており、その値は jQuery コンストラクターであり、これが返され、行 955 (トップ コード) で jQuery 変数に割り当てられます。

jQuery.fn.init

jQuery.fn (上記の 97 行目) はコンストラクター関数 jQuery() のプロトタイプ オブジェクトであり、jQuery.fn.init() は jQuery プロトタイプ メソッドであり、コンストラクターとも呼ばれます。パラメーター セレクターとコンテキストのタイプを解析し、対応する検索を実行します。

パラメータコンテキスト: 渡すことはできません。あるいは、jQuery オブジェクト、DOM 要素、または通常の js オブジェクトの 1 つで渡すことができます
パラメータ rootjQuery: document オブジェクトを含む jQuery オブジェクト。 document.getElementById() の失敗などの状況で使用されます。

コードをコピーします コードは次のとおりです:

jQuery.fn.init.prototype = jQuery.fn = jQuery.prototype
jQuery(セレクター [,コンテキスト])

デフォルトでは、一致する要素の検索はルート要素のドキュメント オブジェクトから開始されます。つまり、検索範囲はドキュメント ツリー全体ですが、2 番目のパラメーターのコンテキストを渡して検索範囲を制限することもできます。例:

コードをコピーします コードは次のとおりです:

$('div.foo').click(function () {
$('span',this).addClass('bar');//検索範囲、つまり上記のコンテキストを制限します
});
jQuery.extend() と jQuery.fn.extend()

メソッド jQuery.extend(object) および jQuery.fn.extend(object) は、2 つ以上のオブジェクトを最初のオブジェクトにマージするために使用されます。該当するソースコードは以下の通り(一部):

コードをコピーします コードは次のとおりです:

jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,//定義されたローカル変数のセット
ターゲット = 引数[0] {},
i = 1,
長さ = 引数.長さ,
深い = false;

jQuery.extend(object); jQuery クラスにクラス メソッドを追加します。これは、静的メソッドの追加として理解できます。例:

コードをコピーします コードは次のとおりです:

$.extend({
add:function(a,b){returna b;}
});

jQuery に add と呼ばれる「静的メソッド」を追加すると、jQuery が導入される場所でこのメソッドを使用できます。

$.add(3,4) //7 を返す
jQuery.fn.extend(object) については、次の公式 Web サイトでコードのデモを確認してください:

コードをコピー コードは次のとおりです:

CSS セレクター エンジン Sizzle

jQuery が DOM を操作するために生まれたと言えるのは、CSS セレクター エンジン Sizzle によるものです。

という解析ルールが挙げられます。

セレクター:"div > p div.aaron input[type="checkbox"]"

解析ルール:
1 右から左にたどってください
2 [type="checkbox"]
などの最後のトークンを取り出します。                                                                                          一致: 配列[3]
タイプ: "ATTR"
                                                                             チェックボックス「]」
} 3 フィルター タイプ タイプが > ~ 空の場合、スキップしてフィルター処理を続行します
ID、CLASS、TAG のいずれかに一致するまで 4 回繰り返します。この方法では、ブラウザー インターフェイスを通じて取得できるためです
5 この時点でシードコレクションには価値があり、ブラシ選択の条件が緩和されます
6. 一致するシード コレクションが複数ある場合は、セレクター セレクターを変更する必要があります: "div > p div.aaron [type="checkbox"]"
7 OK、コンパイル関数の次の段階に進みます



遅延オブジェクト

Web サイトの開発プロセスでは、長時間かかる特定の JavaScript 操作が頻繁に発生します。その中には、非同期操作 (サーバー データの ajax 読み取りなど) と同期操作 (大規模な配列の走査など) の両方があり、結果はすぐには得られません。

通常のアプローチは、コールバック関数を指定することです。つまり、実行終了後にどの関数を呼び出すかを事前に指定します。

しかし、jQuery はコールバック関数に関しては非常に弱いです。これを変更するために、jQuery 開発チームは遅延オブジェクトを設計しました。

簡単に言うと、遅延オブジェクトは jQuery のコールバック関数ソリューションです。英語で defer は「遅延」を意味するため、deferred オブジェクトの意味は、将来の特定の時点まで実行を「遅らせる」ことです。

jQuery の ajax 操作を記述する従来の方法を確認してください:

コードをコピーします コードは次のとおりです: $.ajax({
url: "test.html",
成功: function(){
alert("はは、成功しました!");
}、
エラー:関数(){
alert("何か問題が発生しました!");
}
});


上記のコードでは、$.ajax() はオブジェクト パラメーターを受け入れます。このオブジェクトには 2 つのメソッドが含まれています。success メソッドは操作が成功した後のコールバック関数を指定し、error メソッドは操作が失敗した後のコールバック関数を指定します。

$.ajax() 操作が完了すると、1.5.0 より前のバージョンの jQuery を使用している場合は XHR オブジェクトが返され、バージョンが 1.5.0 より高い場合はチェーン操作を実行できません。 、返された Deferred オブジェクトはチェーン化できます。

さて、新しい書き方は次のとおりです:

コードをコピーします コードは次のとおりです:

$.ajax("test.html")
.done(function(){alert("はは、成功しました!"); })
.fail(function(){alert("エラー!"); });

複数の操作のコールバック関数を指定する

遅延オブジェクトのもう 1 つの大きな利点は、従来の記述では不可能だった複数のイベントのコールバック関数を指定できることです。

新しいメソッド $.when() を使用する次のコードを見てください。

コードをコピーします コードは次のとおりです:

$.when($.ajax("test1.html"), $.ajax("test2.html"))

.done(function(){alert("はは、成功しました!"); })

.fail(function(){alert("エラー!"); });

このコードの意味は、最初に $.ajax("test1.html") と $.ajax("test2.html") の 2 つの操作を実行し、両方が成功した場合、done() 関数で指定されたコールバックを実行することです。 ; どちらかが失敗した場合、または両方が失敗した場合は、fail() で指定されたコールバック関数が実行されます。

jQuery.Deferred(func) の実装原理

成功コールバック関数リスト、失敗コールバック関数リスト、およびメッセージ コールバック関数リストの 3 つのコールバック関数リストが内部で維持されます。他のメソッドはこれら 3 つのリストを中心に動作および検出します。

jQuery.Deferred( func ) のソースコード構造:

コードをコピー コードは次のとおりです:

jQuery.extend({

遅延: function( func ) {
// 成功コールバック関数リスト
var donedList = jQuery.Callbacks( "1 回の記憶" ),
// 失敗時のコールバック関数のリスト
failList = jQuery.Callbacks( "1 回のメモリ" ),
// メッセージコールバック関数リスト
progressList = jQuery.Callbacks( "memory" ),
// 初期状態
状態 = "保留中",
// 非同期キューの読み取り専用コピー
約束 = {
// 完了、失敗、進捗
// 状態、isResolved、isRejected
// その後、常に
// パイプ
// 約束 },
// 非同期キュー 遅延 = Promise.promise({}),
キー;
// 成功、失敗、およびメッセージ コールバック リストをトリガーするメソッドを追加します
for (リスト内のキー) {
deferred[key] = lists[key].fire;
deferred[ key "With" ] = lists[ key ].fireWith;
}
// ステータスを設定するコールバック関数を追加します
deferred.done( function() {
state = "解決済み";
}、failList.disable、progressList.lock )
.fail( function() {
state = "拒否";
}、doneList.disable、progressList.lock );
// 関数パラメータ func が渡されると、それが実行されます。
if ( func ) {
func.call(deferred, deferred);
}

// 非同期キューを遅延して返します

返却遅延;

}、
}


jQuery.when( deferreds )

1 つ以上のオブジェクトの状態に基づいて、通常は非同期イベントを伴う非同期キューに基づいてコールバック関数を実行する機能を提供します。


jQuery.when( deferreds ) の使用法

複数の非同期キュー オブジェクトが渡された場合、メソッド jQuery.when() は、メインの非同期キュー オブジェクトの新しい読み取り専用コピーを返します。この読み取り専用コピーは、渡された非同期キューの最終ステータスを追跡します。

すべての非同期キューが成功すると、「メイン」非同期キューの成功コールバック関数が呼び出されます。

非同期キューの 1 つが失敗すると、メインの非同期キューの失敗コールバック関数が呼び出されます。

コードをコピー コードは次のとおりです:

/*
リクエスト「/when.do?method=when1」は {"when":1}
を返します リクエスト「/when.do?method=when2」は {"when":2}
を返します リクエスト「/when.do?method=when3」は {"when":3}
を返します */
var whenDone = function(){ console.log( 'done', 引数 },
WhenFail = function(){ console.log( 'fail', 引数 };
$.when(
$.ajax( '/when.do?method=when1', { dataType: "json" } ),
$.ajax( '/when.do?method=when2', { dataType: "json" } ),
$.ajax( '/when.do?method=when3', { dataType: "json" } )
).done( whenDone ).fail( whenFail );

画像の説明

非同期キューの遅延

非同期タスクとコールバック関数の分離

ajaxモジュール、キューモジュール、readyイベントの基本機能を提供します。

プロトタイプのプロパティとメソッド

プロトタイプのプロパティとメソッドのソース コード:

コードをコピーします コードは次のとおりです:

97 jQuery.fn = jQuery.prototype = {
98 コンストラクター: jQuery、
99 init: 関数(セレクター、コンテキスト、rootjQuery) {}
210 セレクター: ""、
213 jQuery: "1.7.1"、
216 長さ: 0、
219 サイズ: function() {},
223 toArray: function() {},
229 取得: function( num ) {},
241 PushStack: 関数(要素、名前、セレクター) {},
各 270: function( callback, args ) {},
274 準備完了: function( fn ) {}, //
284 eq: 関数( i ) {},
291 最初: function() {},
295 最後: function() {},
299 スライス: function() {},
304 マップ: 関数(コールバック) {},
310 終了: function() {},
316 プッシュ: プッシュ、
317 ソート: [].ソート、
318 スプライス: [].splice
319 };

セレクター属性は、jQuery が DOM 要素を検索してフィルターするときにセレクター式を記録するために使用されます。
属性 .length は、現在の jquery オブジェクト内の要素の数を表します。
メソッド .size() は、現在の jquery オブジェクト内の要素の数を返します。機能的には属性 length と同等ですが、関数呼び出しのオーバーヘッドがないため、length を最初に使用する必要があります。

.size() のソースコードは次のとおりです:

コードをコピーします コードは次のとおりです:

サイズ():関数(){
this.length を返します;
}

メソッド .toArray() は、現在の jQuery オブジェクトを実際の配列に変換します。変換された配列には、すべての要素が含まれます。

コードをコピーします コードは次のとおりです:

toArray: function() {
return slide.call( this );
}、

Method.get(index) は、現在の jQuery オブジェクト内の指定された位置にある要素、またはすべての要素を含む配列を返します。そのソース
コードは次のとおりです:

コードをコピーします コードは次のとおりです:

取得: function(num) {
return num == null ?

// 「クリーンな」配列を返します
This.toArray():

// オブジェクトのみを返します
( num }、


パラメーターが渡されない場合、 .toArray() を呼び出すと、ロックされた要素を含む配列が返されます。パラメーターのインデックスが指定されている場合、インデックスは 0 からカウントされ、負の数をサポートします。

まず、num が 0 未満かどうかを判定します。0 未満の場合は、添字を長さ num で再計算し、配列アクセス演算子 ([]) を使用して要素を取得します。指定された位置。これは負の添え字をサポートする小さなメソッドです。0 以上の場合は、指定された位置の要素を直接返します。

eg() と get() の使用方法の詳細な説明: 一般的な jquery メソッドと使用例の概要

メソッド .each() は、現在の jQuery オブジェクトを反復処理し、各要素でコールバック関数を実行するために使用されます。 Method.each() は、静的メソッド jQuery.each() を呼び出すだけで内部的に実装されます。

コードをコピーします コードは次のとおりです:
各: function( callback, args ) {
return jQuery.each( this, callback, args );
}、

コールバック関数は、現在の要素がコンテキストであるコンテキスト、つまりキーワード this が常に現在の要素を指すコンテキストでトリガーされ、コールバック関数で false を返すとトラバーサルを終了できます。

メソッド .map() は、現在の jQuery オブジェクトを反復処理し、各要素でコールバック関数を実行し、コールバック関数の戻り値を新しい jQuery オブジェクトに入れます。このメソッドは、DOM 要素のコレクションの値を取得または設定するためによく使用されます。

コードをコピーします コードは次のとおりです:
マップ: function( callback ) {
return this.pushStack( jQuery.map(this, function( elem, i ) {
return callback.call(elem, i, elem);
}));
}、

プロトタイプ メソッド .pushStack() は、新しい空の jQuery オブジェクトを作成し、DOM 要素のコレクションをこの jQuery オブジェクトに配置し、現在の jQuery オブジェクトへの参照を保持します。

プロトタイプの method.pushStack() は、次のメソッドのサポートを提供するコア メソッドの 1 つです:

jQuery オブジェクト トラバーサル: .eq()、.first()、.last()、.slice()、.map()。

DOM の検索とフィルタリング: .find()、.not()、.filter()、.closest()、.add()、.andSelf()。

DOM トラバーサル: .parent()、.parents()、.parentsUntil()、.next()、.prev()、.nextAll()、.prevAll()、.nextUnit()、.prevUnit() 、.siblings()、.children()、.contents()。

DOM 挿入: jQuery.before()、jQuery.after()、jQuery.replaceWith()、.append()、.prepent()、.before()、.after()、.replaceWith()。

3 つのパラメータを受け入れるメソッド .push(elems, name, selector) を定義します:

パラメータ elems: 新しい jQuery オブジェクトに入れられる要素の配列 (または配列のようなオブジェクト)。

パラメータ名: 要素配列 elems を生成する jQuery メソッドの名前。

パラメーター セレクター: jQuery メソッドに渡されるパラメーター。プロトタイプのattribute.selector を変更するために使用されます。

メソッド .end() は、現在のチェーン内の最新のフィルタリング操作を終了し、一致する要素を以前の状態に戻します

コードをコピーします コードは次のとおりです:
終了: function() {
return this.prevObject || this.constructor(null);
}、

前の jQuery オブジェクトを返します。prevObect 属性が存在しない場合は、空の jQuery オブジェクトが構築されて返されます。メソッド .pushStack() はスタックにプッシュするために使用され、メソッド .end() はスタックからポップアウトするために使用されます

静的プロパティとメソッド

関連するソースコードは次のとおりです:

コードをコピー コードは次のとおりです:

388 jQuery.extend({
 389 noConflict: function( deep ) {},
 402 isReady: false,
 406 readyWait: 1,
 409 holdReady: function(hold) {},
 418 準備完了: function( wait ) {},
 444 bindReady: function() {},
 492 isFunction: function( obj ) {},
 496 isArray: Array.isArray || function( obj ) {},
 501 isWindow: function( obj ) {},
 505 isNumeric: function( obj ) {},
 509 タイプ: function( obj ) {},
 515 isPlainObject: function( obj ) {},
 544 isEmptyObject: function( obj ) {},
 551 エラー: function( msg ) {},
 555 parseJSON: function( data ) {},
 581 parseXML: function( data ) {},
 601 noop: function() {},
 606 globalEval: function( data ) {},
 619 キャメルケース: function( string ) {},
 623 ノード名: function( elem, name ) {},
 628 各: function( object, callback, args ) {},
 669 トリム: トリム ? function( テキスト ) {} : function( テキスト ) {},
 684 makeArray: function( 配列, 結果 ) {},
 702 inArray: function( elem, array, i ) {},
 724 マージ: function( first, Second ) {},
 744 grep: function( elems, callback, inv ) {},
 761 マップ: function( elems, callback, arg ) {},
 794 ガイド: 1,
 798 プロキシ: function( fn, context ) {},
 825 アクセス: function( elems, key, value, exec, fn, pass ) {},
 852 現在: function() {},
 858 uaMatch: function( ua ) {},
 870 サブ: function() {},
 891 ブラウザ: {}
 892 });
 

まだ準備ができていません、、、今日は先にここに来て、次に行きます。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。