2

私のプロジェクトには次のファイルが含まれています。

./index.html
./js/main.js
./js/vendor/require.js
./js/viewmodel/vm.js

index.htmlは、次の関連するスニペットがあります。

<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
    require(['viewmodel/vm', 'ko'], 
        function(viewmodel, ko) {
            ko.applyBindings(viewmodel);
        }
    );
</script>

ファイルは次のjs/main.jsとおりです。

var root = this;
define('jquery', ['http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.js'], function () { return root.$; });
define('ko', ['http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.1.0.js'], function (ko) { return ko; });

ファイルjs/viewmodel/vm.js...

define(['jquery', 'ko'], 
    function($, ko) {
        return {
            subject: 'world',
            greeting: 'hello'
        }
    }
);

ブラウザを開いてindex.htmlを開くと、ブラウザはjs/ko.jsで定義されたモジュールを使用する代わりに、と呼ばれるファイルを読み込もうとしますmain.js。data-main属性が指すjsファイルは、依存関係が解決される前に実行されることが保証されていないようです。data-main jsファイルの目的の1つは、require構成(つまり、パス、shimなど)を定義することであるため、これは私には正しくないようです。requirev2.1.2を使用しています。

main.jsファイルの内容をのスクリプトブロックにコピーすると、これは完全に正常に機能しますindex.html。「完全に問題ない」とは、koをモジュールとして解決し、ダウンロードを試みる代わりに、koを解決するための適切なCDNリンクを見つけることを意味します./js/ko.js

4

3 に答える 3

12

data-mainアプリケーション全体を構成するために属性を使用するには、それがすべてのコードの単一のエントリポイントである必要があります。

2番目のスクリプトブロックは、2番目のエントリポイントを提供することでこの要件を破ります。これらのエントリポイントは互いに独立して(そして非同期に)解決されるため、一方に依存して他方に影響を与えることはできません。

これを解決するには、アプリケーションに単一のエントリポイントを提供する方法でコードをリファクタリングし、このエントリポイントを介して構成を行います。

于 2012-11-30T18:35:49.373 に答える
7

これは、requirejsが非同期を設定するためです。スクリプトの属性。

スクリプト要素のブール非同期属性により、外部JavaScriptファイルが利用可能になったときに、最初にページの読み込みを遅らせることなく実行できます。

これは、両方のスクリプトが並行してロードおよび評価されるため、2つのスクリプトのいずれも他方からメソッドまたは関数にアクセスできないことを意味します。1つのスクリプトでrequirejs変数を定義する場合は、requirejsを使用してそのスクリプトをロードしないでください。

私にとって、その問題を解決する方法は3つあります。

  • main.jsのコンテンツをページに追加します(あなたが言うように)
  • 通常のスクリプトとしてrequirejsなしでmain.jsファイルをロードします
  • スクリプトをロードする前にrequireconfigを定義します(requirejs docuへのリンク
于 2012-11-30T08:05:35.587 に答える
1

私も同じ問題を抱えていました。私が働いていたサイトのアーキテクチャは、ページの各部分で非同期にロードされていたコンポーネントでした。各コンポーネントには、独自のhtml、css、およびjsコードがあります。したがって、私の解決策は、必要なすべての依存関係コードのガード関数を保持して、メインのjavascriptファイルの前に実行されないようにすることです。

index.html

<head>
<script type="text/javascript">
    window.BeforeMainGuard = {
        beforeMainLoadedFunctions: [],
        hasMainLoaded: false,
        guard: function( func ) {
            console.assert( typeof func === 'function' );
            if( this.hasMainLoaded ) {
                func();
            }else {
                this.beforeMainLoadedFunctions.push( func );
            }
        },
        onMainLoaded: function() {
            for( var i = 0; i<this.beforeMainLoadedFunctions.length; ++i ) {
                var beforeMainLoadedFunction = this.beforeMainLoadedFunctions[i];
                  beforeMainLoadedFunction();
            }
            this.beforeMainLoadedFunctions = null;
            this.hasMainLoaded = true;
        }
    };
</script>
<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
    window.BeforeMainGuard.guard( function() {
        require(['viewmodel/vm', 'ko'], 
            function(viewmodel, ko) {
                ko.applyBindings(viewmodel);
            }
        );
    });
</script>
</head>

js / main.js

require.config({
  // your config
});

require( [ 'AppLogic' ], function( AppLogic ){      
    AppLogic.Init();
    window.BeforeMainGuard.onMainLoaded();
} );
于 2014-10-16T12:19:11.990 に答える