45

これが私のconfig.jsまたはmain.jsであるとしましょう:

require.config({
    // paths are analogous to old-school <script> tags, in order to reference js scripts
    paths: {
        jquery: "libs/jquery-1.7.2.min",
        underscore: "libs/underscore-min",
        backbone: "libs/backbone-min",
        jquerymobile: "libs/jquery.mobile-1.1.0.min",
        jquerymobilerouter: "libs/jquery.mobile.router.min"
    },
    // configure dependencies and export value aliases for old-school js scripts
    shim: {
        jquery: ["require"],
        underscore: {
            deps: ["jquery"],
            exports: "_"
        },
        backbone: {
            deps: ["underscore", "jquery"],
            exports: "Backbone"
        },
        jquerymobilerouter: ["jquery", "backbone", "underscore"],
        jquerymobile: ["jquery", "jquerymobilerouter", "backbone", "underscore"]
    }
});
require(["jquery", "backbone", "underscore", "app/app.min", "jquerymobilerouter", "jquerymobile"], function ($, Backbone, _, App) {
    console.log($);
    console.log(Backbone);
    console.log(_);
    $("body").fadeIn(function () {
        App.init();
    });
});
  1. 私の理解が正しければ、構成オプションを使用すると、 HTML 内pathsのタグなどのスクリプトを参照できます。これが事実であると仮定すると、以下の実際のrequireステートメントで、<script>jQueryのようなスクリプトにa$またはアンダースコアでエイリアスを付ける必要がありますか? 標準タグでjQuery を参照すると、スクリプト全体で自動的に使用できることを_考えると、そうしなければならないのは奇妙に思えます。を使用しても同じではないでしょうか?<script>$paths

  2. 私はshim構成オプションを初めて使用します。これは、非推奨のorder!プラグインに取って代わったことを理解しています。exportsプロパティは実際に何をしますか?スクリプトのエイリアスを作成していないようです。たとえば、exportsfor アンダースコアをに設定して"whatever"から にしようとするとconsole.log(whatever)、未定義になります。それで、ポイントは何ですか?

  3. jQuery のようなスクリプトを「グローバル」に適切に使用するにはどうすればよいでしょうか? $つまり、App.js モジュール内、または "app" フォルダー内の他のモジュール内でエイリアスを使用できる適切な方法は何ですか? 個々のモジュールとエイリアスごとに毎回 jQuery を要求する必要があります$か? それとも、ここで行った方法は適切な方法ですか?

この特定のスクリプトに対するその他の批判も大歓迎です。私の意見では、Require.js のドキュメントには多くの要望が残されています。もっと知りたいと思っていたことが、ごまかされてしまい、頭を悩ませているようです。

4

2 に答える 2

23

に関する混乱を解消するためにexports、シム ライブラリはプロパティをグローバル コンテキスト (windowまたはroot) にアタッチするか、既存のグローバル プロパティ (jQuery プラグインなど) を変更すると想定しています。requireJS は、shim された依存関係をロードするコマンドを取得すると、exportsその shim 構成の値と一致するプロパティのグローバル コンテキストを調べ、見つかった場合は、そのモジュールの値として返します。見つからない場合は、関連するスクリプトをロードし、実行されるのを待ってから、グローバル シンボルを見つけて返します。

覚えておくべき重要な事実は、シム構成にexports値が含まれていない限り、その構成のinitメソッドは実行されないということです。依存関係ローダーは、モジュールexportsを初期化する前に、モジュールの値 (指定するもの) を見つける必要があります。これが、そのモジュールに shim がある場合にプロパティが必要な理由initです。

更新:問題のモジュールがdefineどこかで呼び出された場合、そのモジュール用に持っているシム構成は無視されることも指摘する必要があります。jQuery.noConflict(true)シム構成を使用してjQueryのメソッドを呼び出してjQueryのグローバル化を解除し、それを必要とするモジュールだけにスコープを限定したかったので、これは実際に頭痛の種になりましたが、それを機能させることができませんでした。(シム構成の代わりにマップ構成を使用してこれを簡単に行う方法については、下部の更新を参照してください。)

更新 2: requireJS Google グループに関する最近の質問で、私の説明が少し誤解を招く可能性があることに気付きました。そのため、明確にしたいと思います。RequireJS は、requireJS を介して少なくとも 1 回ロードされた場合にのみ、shim された依存関係を再利用します。つまり<script>、ホスティング ページにタグ (アンダースコアなど) がある場合は、次のようになります。

<script src='lib/underscore.js'></script>
<script src='lib/require.js' data-main='main.js'></script>

...そして、requireJS構成に次のようなものがあります:

paths: {
    'underscore': 'lib/underscore'
},
shim: {
    'underscore': {
        exports: '_'
    }
}

define(['underscore'], function (_) {});次にorを初めて実行するvar _ = require('underscore');と、RequireJS は、以前に定義された を再利用するのではなく、アンダースコア ライブラリを再読み込みしwindow._ます。_確かに、ルート スコープで が既に定義されているかどうかを確認できます_が、既に存在する が構成で定義されているものと同じであることを確認する方法はありませんpaths。たとえば、 と の両方がデフォルトprototypejquery割り当てられてwindow.$おり、requireJS が「window.$」が実際にはプロトタイプであるのに jQuery であると想定すると、悪い状況になります。

つまり、このようにスクリプトをロードするスタイルを組み合わせると、ページは次のようになります。

 <script src='lib/underscore.js'></script>
 <script src='lib/require.js' data-main='main.js'></script>
 <script src='lib/underscore.js'></script>

2 番目のアンダースコア インスタンスは、requireJS によって読み込まれたインスタンスです。

基本的に、requireJS がそれを知るには、requireJS を介してライブラリをロードする必要があります。ただし、次にアンダースコアが必要になったときに、requireJS は「ねえ、既にそれを読み込んでいるので、exports値が何であれ返してください。別のスクリプトを読み込むことを心配する必要はありません」となります。

これは、2 つの実際のオプションがあることを意味します。1 つは、私がアンチパターンと考えるものです。つまり、requireJS を使用してグローバル スクリプトの依存関係を表現しないでください。つまり、ライブラリがルート コンテキストにグローバルをアタッチしている限り、その依存関係が明示的に必要とされていない場合でも、それにアクセスできます。これがアンチパターンである理由がわかります。基本的に、AMD ローダーを使用する利点のほとんどを排除しただけです (明示的な依存関係のリストと移植性)。

もう 1 つのより良いオプションは、requireJS を使用してすべてをロードすることです。実際に自分で作成するスクリプト タグは、requireJS を最初にロードするものだけにする必要があります。シムを使用することもできますが、95% の場合、代わりに AMD ラッパーをスクリプトに追加することはそれほど難しくありません。AMD 以外のすべてのライブラリを AMD と互換性を持つように変換するには、もう少し作業が必要になる場合がありますが、1 つまたは 2 つの作業を完了すると、はるかに簡単になります。一般的な jQuery プラグインを使用して、AMD モジュールに変換できます。 1分以内に。通常は追加するだけです

define(['jquery'], function (jQuery) {

上部に、そして

    return jQuery;
});

底に。jQueryではなく「jquery」マッピングを使用する理由$は、最近のほとんどのプラグインが次のようなクロージャーにラップされていることに気付いたからです。

(function ($) {
    // plugin code here
})(jQuery);

そして、意図した範囲に注意を払うことをお勧めします。$ただし、プラグインjQuery$. これは単なる基本的な AMD ラッパーです。より複雑なものは、一般に、使用されているローダーの種類 (commonJS と AMD と通常の古いグローバル) を検出しようとし、結果に応じて異なる読み込み方法を使用します。この例は、Google で数秒で簡単に見つけることができます。

jQuery.noConflict(true)更新: RequireJS での使用をサポートしていた回避策は機能しましたが、jQuery ソースに非常に小さな変更を加える必要がありました。その後、jQuery を変更せずに同じことを達成するためのはるかに優れた方法を見つけました。幸いなことに、RequireJS の作成者である James Burke も RequireJS のドキュメントに追加してくれました: http://requirejs.org/docs/jquery.html#noconflictmap

于 2013-02-26T20:33:20.133 に答える
22
  1. パスは、require.jsに、その依存関係が必要なときにどこを見ればよいかを伝えます。

    たとえば、私は次のように構成されています。

    "paths": { 
        "jquery": "require_jquery"
    },
    "shim": {
        "jquery-cookie"  : ["jquery"],
        "bootstrap-tab"  : ["jquery"],
        "bootstrap-modal": ["jquery"],
        "bootstrap-alert": ["jquery"]
    },
    

    これは、モジュールで毎回行うことを意味します

    define( ['jquery']
    

    requirejsは、jquery.jsをロードrequire_jqueryしようとするのではなく、メインパスからファイルをロードします。あなたの場合、それはjQueryソースファイルをロードし、それはグローバルに利用可能になります。私は個人的にそのアプローチが好きではありません。そのため、require_jquery.jsファイルでは次のようにしています。

    define( ["jquery_1.7.2"], function() {
        // Raw jQuery does not return anything, so return it explicitly here.
        return jQuery.noConflict( true );
    } );
    

    これは、jQueryがモジュール内でのみ定義されることを意味します。(これは、Wordpressプラグインを作成しているため、外部バージョンに触れることなく、独自のバージョンのjQueryを含めることができるためです)

  2. エクスポート(ドキュメントからの読み取りは、ロードが正しく行われたかどうかを検出できるように、使用しているモジュールの名前である必要があります。ここで説明します。したがって、アンダースコアのエクスポートを設定する場合は、_

  3. 私が説明したように、jQueryはグローバルである必要があります。単にインポートすると、ファイルが実行され、jQueryはグローバルになります。

編集-コメントに答えます。

  1. はい、つまり、jQueryの場合は$またはjQueryをエクスポートし、バックボーンの場合は_をエクスポートする必要があります。私がドキュメントから得たものから、これは一部のエッジケースでのみ必要であり、グローバル名前空間でjQueryとして自分自身を宣言するライブラリには必要ありません。

    CDNからjQueryをロードすることからフォールバックする必要がある場合、requirejsはそれらを必要とすると思います。requirejsは最初にCDNからjQueryをロードしようとし、次に「エクスポートされた」変数が存在することを確認することで正しくロードされたことを確認し、ロードされない場合はローカルファイルシステムからロードすると思います(もちろん、フォールバックを構成していました)。これは、requirejsが404が戻ってくるのを認識できない場合に必要なものです。

  2. jQueryはグローバルに宣言されているため、グローバルに利用できます。単純にjQueryスクリプトをロードして実行すると、2つのグローバルが作成され$ますjQuery(または、私が行ったように実行して、それを回避できます)。関数内では、define()jQueryを任意のエイリアスにすることができます。

    define( [ 'jquery' ], function( jq ) {
        // jq is jquery inside this function. if you declared it 
        // globally it will be also available as $ and jQuery
    } );
    
于 2012-06-14T15:02:53.217 に答える