RequireJS загружает угловое приложение, но не создает app.controller

Я настроил очень простую среду для загрузки компонентов AngularJS (которые управляются Bower) с помощью RequireJS. Мой index.html очень прост:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular Resource Test</title>
</head>
<body>

    <div ng-controller="MyCtrl">
        <ul>
            <!-- this template is not populated -->
            <li ng-repeat="item in items">{{item}}</li>
        </ul>
    </div>

    <script type="text/javascript" src="bower_components/requirejs/require.js" data-main="scripts/main"></script>
</body>
</html>

Мой RequireJS находится в main.js, что выглядит так:

requirejs.config({
    baseUrl: 'bower_components',
    paths: {
        'angular': '../bower_components/angular/angular',
        'angular-resource': '../bower_components/angular-resource/angular-resource'
    },
    shim: {
        'angular': {
            exports: 'angular'
        },
        'angular-resource': {
            deps: ['angular'],
        }
    },
});

define("app", ["angular", "angular-resource"], function(angular) {
    var app = angular.module('MyApp', ['ngResource']);
    return app;
});

require(["app"], function(app) {
    console.log(app); // this works
    app.controller("MyCtrl", ['$scope', '$resource',
        function($scope, $resource) {
            console.log("hello"); // this doesn't work
            $scope.items = [1, 3, 4, 5];
        }
    ]);
});

Кажется, что все зависимости разрешены и загружены, и создается экземпляр приложения Angular. Однако я не могу зарегистрировать контроллер Angular. Оператор console.log() внутри функции обратного вызова не выполняется, поэтому кажется, что создание контроллера полностью завершилось неудачей?

/редактировать:

Добавление директивы ng-app к <body> приводит к этой ошибке:

Uncaught Error: [$injector:modulerr] Не удалось создать экземпляр модуля MyApp из-за: Ошибка: [$injector:nomod] Модуль MyApp недоступен! Вы либо неправильно написали имя модуля, либо забыли его загрузить. При регистрации модуля убедитесь, что вы указали зависимости в качестве второго аргумента.

Вы можете найти полный проект на GitHub, если это сделает его более понятным.


person doque    schedule 23.03.2015    source источник


Ответы (2)


Есть несколько вещей, которые следует/можно исправить в вашем коде.

  • Отсутствует angular.bootstrap(document, ['MyApp']);. Потому что, когда вы используете requireJS, angular.bootstrap() является необходимостью. Вместо того, чтобы angular получил инициализацию сразу при загрузке скрипта, сначала требуется получить инициализацию. И это приведет к сбою вашего приложения. Чтобы заставить его работать, вам нужно подождать require init =>, затем он загрузит angular и init angular => после того, как все будет сделано, загрузите ваше приложение.
  • define() предполагается обернуть весь код модуля/файла
  • require() Используется для вызова модуля/файла.
  • RequireJS используйте для разделения ваших модулей на файлы. Таким образом, будет проще управлять и, возможно, сократить время загрузки вашего приложения, если вы правильно настроите его. Поместив множество модулей в файлы. Вы только что испортили цель использования requireJS. (например, я создал приложение, в котором общий объем кода, плагинов и HTML-кода составляет около 3 МБ. Но при загрузке первой страницы это всего 400 КБ, круто, а?)

Вы можете попробовать что-то вроде следующего:

requirejs.config({
    baseUrl: 'bower_components',
    paths: {
        'angular': '../bower_components/angular/angular',
        'angular-resource': '../bower_components/angular-resource/angular-resource',
        'app' : '../scripts/app' // 'app' is the module name. It got defined by define() block, and  can be loaded by either require() or define() block
    },
    shim: {
        'angular': {
            exports: 'angular'
        },
        'angular-resource': {
            deps: ['angular'],
        }
    },
});



require(["app"], function(app) {
    console.log(app);
    app.controller("MyCtrl", ['$scope', '$resource',
        function($scope, $resource) {
            console.log("hello"); // this doesn't work
            $scope.items = [1, 3, 4, 5];
        }
    ]);

    angular.bootstrap(document, ['MyApp']);
});

и внутри вашего app.js

define(["angular", "angular-resource"], function(angular) {
    var app = angular.module('MyApp', ['ngResource']);
    return app;
});
person Linh Pham    schedule 23.03.2015
comment
Просто отредактировал пару опечаток и попытался использовать более подходящие слова для объяснения. - person Linh Pham; 23.03.2015
comment
Я изменил свою файловую структуру, как вы предложили, но поведение осталось прежним. См. github.com/doque/angular-requirejs. - person doque; 23.03.2015
comment
@doque позвольте мне взглянуть на это - person Linh Pham; 23.03.2015
comment
@doque хорошо, я ошибаюсь. Я обновлю ответ в ближайшее время. Вам просто не хватает angular.bootstrap(document, ['MyApp']);. - person Linh Pham; 23.03.2015
comment
Это не помогает, к сожалению. Я обновил код на GitHub. - person doque; 23.03.2015
comment
для меня это было работой, когда я использую ваш код на github ... хорошо, тогда я попробую на github. РЕДАКТИРОВАТЬ: и я проверил ваш код, вы добавили его не в то место. Взгляните на мой ответ еще раз. Если вы просто скопируете его в свой проект. Это сработает. И за использование модуля в качестве контроллера. Я предлагаю вам тоже взглянуть на angularAMD - person Linh Pham; 23.03.2015

Вы загрузили angular, но вам еще предстоит его загрузить, так как вы загружаете свои скрипты динамически, использование атрибута ng-app не вариант, поэтому вам нужно позвонить

angular.bootstrap(document.body, ['app']);

см. https://docs.angularjs.org/api/ng/function/angular.bootstrap

person Lee Elenbaas    schedule 23.03.2015
comment
Я сделал это, но почему-то app все еще не передается контроллеру. Я получаю сообщение об ошибке Error: [ng:areq] Argument 'MyCtrl' is not a function, got undefined, что обычно означает, что возвращаемое значение модуля неверно. Но как это может быть? - person doque; 23.03.2015
comment
У меня точно такая же проблема, я думаю, это связано с тем, что контроллер загружается до самого приложения.. (через атрибут ng?), так что какой должен быть правильный подход для части контроллеров - person Jacob; 14.07.2015
comment
stackoverflow .com/questions/25383540/ посмотрите на этот пример или используйте angularAMD здесь: plnkr. co/edit/azsKJnFJ0pYwBW0dGMFH?p=preview - person Jacob; 14.07.2015