JavaScriptモジュラー開発ライブラリのSeaJS
SeaJSは国内の天才lifesinger氏によって開発されました。現在のバージョンは 1.1.1 で、ソース コードは 1500 行未満で、4k に圧縮されており、品質は非常に高くなっています。
この記事では、SeaJS の基本的な使い方について説明します。すべてを網羅するわけではありませんが、私の個人的な理解に基づいて、公式ドキュメントには記載されていないいくつかの詳細について説明します。
1. SeaJS のグローバル インターフェイス
SeaJS は 2 つの識別子を世界に公開します: seajs と define。
プロジェクトで識別子 seajs をすでに使用していて、それを変更したくない場合。現時点では、SeaJS はグローバル SeaJS を放棄できます。たとえば、
var boot = seajs.noConflict();
このとき、boot は以前の seajs と同等になります。
プロジェクト内で定義された識別子を使用する場合でも、それを変更したくありません。 SeaJS は非常に寛容であり、その定義を譲渡することもできます。たとえば、
var boot = seajs.noConflict(true);
は、上記よりも true を 1 つだけ渡します。現時点では、グローバル定義はなくなりました。現時点では、boot.define を使用して以前の定義を置き換える必要があります。
jQuery を使用したことのある学生は $.noConflict メソッドに精通しているはずで、SeaJS の noConflict はそれに似ています。
2. SeaJS モジュールの記述方法
SeaJS は、デフォルトでグローバル定義関数を使用してモジュールを記述します (define は、id、deps、factory の 3 つの仮パラメータを定義します)。
define(id?, deps?, Factory);
この定義は、AMD の唯一の API、define 関数を簡単に思い出させることができます。 あるいは、混乱を招くため、SeaJS と RequireJS の定義の違いについて混乱が生じます。
それらはすべて 3 つの仮パラメータを持つグローバル定義を持ち、対応する仮パラメータ名も同じです。SeaJS が AMD の実装であると誤解されます。
実際、SeaJS と RequireJS の定義の最初の 2 つのパラメーターは同じです。
ID はすべて文字列であり、モジュール識別子の後に続きます。 deps はすべて依存モジュールを参照し、その型は配列です。唯一の違いは 3 番目のパラメーター ファクトリです。型も関数ですが、ファクトリ パラメーターの意味は異なります。
RequireJS
a 要素と deps (array) 要素のファクトリ パラメーターには 2 つの状況があり、1 対 1 に対応します。つまり、いくつかの dep があり、factory の実際のパラメータもいくつかあります。
define(['a', 'b'], function(a, b){
// todo
});
b、require、exports、module(モジュール/ラッピング形式)に修正。
define(function(require,exports,module){
// todo
});
このメソッドは、RequireJS を Modules/Wrappings に後から妥協したもの、つまり互換性があります。 SeaJS の定義では、RequireJS の 2 番目の記述方法であるモジュール/ラッピングのみがサポートされています。
注: SeaJS は Modules/Wrappings および Modules/1.1.1 に従います。これら 2 つの仕様では、define キーワードについては言及されていません。モジュール/ラッピングでは、define の代わりに module.declare を使用してモジュールを定義する必要があります。ただし、define の定義があるのは AMD 仕様のみです。つまり、SeaJS は AMD の実装ではありませんが、非常に誤解されやすい識別子定義を使用しています。
ここまで言いましたが、まだモジュールを書き始めていません。最も単純な
1 から始めましょう。単純なモジュール
define({
addEvent: function(el, type, fn){},
removeEvent: function(el, type, fn){},
fireEvent: function(el , type ){}
});
このようにしてイベントモジュールが書かれますが、これはシングルトンを書くのと変わりません。この方法は、純粋なデータ モジュールを定義するためによく使用されます。これは
var E = {
addEvent: function(el, type, fn){},
RemoveEvent: function(el, type, fn){},
fireEvent: function(el, type){}
} に似ています。 ;
2. 単純なパッケージ化モジュール
define(function() {
// いくつかの内部補助関数
// ...
function addEvent() {
}
function RemoveEvent() {
// ..
}
function fireEvent() {
} // ..
}
return {
addEvent,
RemoveEvent:moveEvent,
fireEvent: fireEvent
};
});
ご存知のように、この匿名の中でできることはたくさんあります関数で。最後に必要なインターフェイスを公開するだけです。これは
var E = function() {
// いくつかの内部ヘルパー関数
// ...
function addEvent() {
} }
function RemoveEvent() // ..
}
function fireEvent() { ️ ;addEvent: addEvent,
removeEvent:removeEvent,
fireEvent:fireEvent
};
}();
3. NodeJS スタイルのパッケージ化モジュール
上記 2 つの記述には NodeJS スタイル (Modules/1.1.1) の痕跡はありません。 「方法 2」と同等のものとして書き換えます。
define(function(require,exports) {
// いくつかの内部ヘルパー関数
// ...
function addEvent() {
// ..
}
function RemoveEvent() {
// ..
}
function fireEvent() {
オブジェクトを返す代わりにエクスポートを使用してモジュールインターフェイスをエクスポートします。 ,,, function fireEvent() ;
「方法 2」との違いは次のとおりです。
1: 匿名関数には 2 つのパラメータがあります。そして輸出。
2: エクスポート インターフェイスはオブジェクトを返しませんが、エクスポートを使用します。
そして、エクスポートはまさに NodeJS のスタイルではないでしょうか? 注意深い学生は、この例では require パラメータが使用されていないことに気づくかもしれません。これについては以下で説明します。
4. 依存関係のあるモジュール
SeaJS の「依存関係」は、require 関数を使用して取得する必要があります。SeaJS の define の 2 番目のパラメータ deps も「依存関係」を意味しますが、これはパッケージ化ツール (SPM) によって使用されます。さらに、SeaJS の require はパラメータとして匿名関数に渡され、RequireJS の require はグローバル変数です。 www.2cto.com
上記の定義は依存関係のないモジュールであり、以下は依存関係のあるモジュールです。
define(function(require,exports) {
var Cache = require('cache');
// ...
exports.bind = binding;
exports.unbind = unbind;
exports.trigger = トリガー;
});
このイベントモジュールはキャッシュモジュールに依存しており、関数には2つの仮パラメータrequireとexportsがあります。外部の匿名関数と定義は別として、これは標準の NodeJS 形式です。依存モジュールを取得するには require 関数を使用し、既存のモジュール インターフェイスをエクスポートするにはエクスポートを使用します。
実際、SeaJS の依存関係を持つモジュールは「方法 4」に従って記述する必要があります。つまり、ラッパー モジュールである必要があり、匿名関数の最初のパラメータは識別子「require」である必要があります。つまり、グローバルではありませんが、require を元の構文のキーワードとして使用できます。
匿名関数のパラメーター require とエクスポートの興味深い現象をいくつか見てみましょう
a 書かれているものが require ではない場合、req に変更すると結果はどうなるでしょうか。
define(function(req,exports){
varcache = req('cache');
// ...
exports.bind = binding;
exports.unbind = unbind;
exports.trigger = トリガー;
});
Firebug ネットワーク リクエストは次のとおりです
依存する「キャッシュ」がロードされていないことがわかり、もちろん JS は間違いなくエラーを報告します。
b. 匿名関数の仮パラメータのみを req に変更し、関数内では引き続き require を使用します。
var Cache = require('cache');
// ...
exports.bind = バインド;
Exports.unbind = アンバインド;
Exports.trigger = トリガー;
});
ネットワークリクエストを見てください
今回は「キャッシュ」モジュールが実際にリクエストされました。
上記の匿名関数コードを注意深く見てください。ここでは、require が宣言されておらず、仮パラメータ req も require されていません。それでは、
?
1 var queue = require('cache');
の require はどこから来たのでしょうか?
SeaJS ソース コードを見ると、その定義関数が匿名関数の toString を取得し、通常のマッチングを使用して「キャッシュ」を解析することがわかります (プライベート parseDependency 関数)。
また、キャッシュ リクエストが完了しても、実行フェーズ中に require が定義されていないため、エラーが依然として報告されていることもわかります。したがって、依存モジュールを作成する場合、無名関数の最初のパラメータは必須である必要があり、変更することはできません。
factory.toString と通常の解析依存関係が使用されるため、require のパラメーターは次のような式にすることはできません
// require のパラメーターを式操作にすることはできません
require("ui-" + "dialog");
また、require のエイリアスも使用できません。
// require を別の変数に代入することはできません
var req = require;
req("ui-dialog");
c. expo
define(function() にエクスポートを変更します。 require , expo) {
var queue = require('cache');
// ...
expo.bind = バインド;
expo.unbind = アンバインド;
expo.trigger = トリガー;
});
走行には問題ありません。つまり、2 番目のパラメータ「exports」はカスタマイズできます。明らかに、SeaJS は「エクスポート」を別のものに変更することに同意していません。これは明らかに NodeJS スタイル (Modules/1.1.1) モジュール仕様を破壊します -- 彼らはモジュール インターフェースをエクスポートするために「エクスポート」を使用します。しかし、これは SeaJS で強制することはできず、人為的な合意にすぎません。
5. 書き方が混在するモジュール
以上、様々な場面でのモジュールの書き方を紹介しました。 NodeJS スタイルとの一貫性を保つために、「依存関係」を取得するには require を使用し、「インターフェース」をエクスポートするには exports を使用します。 SeaJS には依存関係の取得に関する制限があります。つまり、require を使用する必要があります。ただし、エクスポートを使用する必要はありません。つまり、エクスポートを別のものに変更できます。 「戻り値」を直接使用することもできます。
define(function(require) {
var Cache = require('cache');
// ...
// 戻り値を使用してインターフェイスをエクスポートします
return {
binding: function() {},
unbind: Function () {},
Fire: function () {}}
});
nodejs のモジュールはオブジェクトのみであることがわかっています。つまり、エクスポートでは常にメソッドをハングさせます。エクスポートを使用して SeaJS のインターフェイスをエクスポートする場合も、モジュールは JS オブジェクトのみに当てはまります。 「戻り値」を使用してインターフェースをエクスポートする場合、モジュールは任意の JS タイプにすることができます。以下は関数タイプのモジュールを返します。 FDefine(function(request) {
var Cache = reques ('cache');
3. SeaJSの読み込み方法
様々な読み込み方法(同期・非同期)が用意されていますが、最も簡単なのはページ内に直接スクリプトタグを記述することです。 。 SeaJS を導入した後、ほとんどの場合、 seajs.use メソッドを開始します。
seajs.use には 2 つのパラメータがあり、最初のパラメータは文字列 (モジュール名) または配列 (複数のモジュール) です。 2 番目のパラメータはコールバック関数です。モジュールのロード後のコールバック。コールバック関数のパラメータは第 1 パラメータと 1 対 1 に対応します。
seajs.use('dom', function(dom) {
// todo with dom
});
domモジュールは以下のようにコールバック関数内で使用されます。もちろん、ショートカット data-main (RequireJS と同じ) も提供します。