угловой-ui-маршрутизатор с требованием, ленивая загрузка controllerа

Не могли бы вы помочь мне понять, как загрузить controller в примере ниже перед представлением? Похоже, что представление загружается сразу же, пока controller еще не загружен.

//app.js $stateProvider.state('index', { url: "/", views: { "topMenu": { templateUrl: "/Home/TopMenu", controller: function($scope, $injector) { require(['controllers/top-menu-controller'], function(module) { $injector.invoke(module, this, { '$scope': $scope }); }); } } } }); //top-menu-controller.js define(['app'], function (app) { app.controller('TopMenuCtrl', ['$scope', function ($scope) { $scope.message = "It works"; }]); }); //Home/TopMenu 

TopMenu

{{message}}

    2 Solutions collect form web for “угловой-ui-маршрутизатор с требованием, ленивая загрузка controllerа”

    Здесь я создал рабочий плункер .

    Давайте получим этот index.html :

     < !DOCTYPE html>   my lazy   #/home // we have three states - 'home' is NOT lazy #/ - index // 'index' is lazy, with two views #/other // 'other' is lazy with unnamed view 
    // standard angular // and ui-router scritps // our application

    Давайте посмотрим на main.js – config RequireJS:

     require.config({ //baseUrl: "js/scripts", baseUrl: "", // alias libraries paths paths: { // here we define path to NAMES // to make controllers and their lazy-file-names independent "TopMenuCtrl": "Controller_TopMenu", "ContentCtrl": "Controller_Content", "OtherCtrl" : "Controller_Other", }, deps: ['app'] }); 

    Фактически, мы создаем только псевдонимы (пути) для наших ControllerNames – и их файлы Controller_Scripts.js . Вот и все. Кроме того, мы возвращаемся к требованию приложения, но в нашем случае мы будем использовать другую функцию позже – для регистрации лениво загруженных controllerов.

    что означает deps: ['app'] ? Во-первых, нам нужно предоставить файл app.js («app» означает find app.js ) :

     define([], function() { var app = angular.module('app'); return app; }) 

    это возвращаемое значение – это тот, который мы можем запросить в каждом загруженном асинхронном файле

     define(['app'], function (app) { // here we would have access to the module("app") }); 

    Как мы будем лениво загружать controllerы? Как уже доказано здесь для ngRoute

    angularAMD v0.2.1

    angularAMD – это утилита, которая облегчает использование RequireJS в приложениях AngularJS, поддерживающих по требованию загрузку сторонних модhive, таких как угловые-ui.

    Мы запросим угловую ссылку на $controllerProvider – и используем ее позже для регистрации controllerов.

    Это первая часть нашего script.js :

     // I. the application var app = angular.module('app', [ "ui.router" ]); // II. cached $controllerProvider var app_cached_providers = {}; app.config(['$controllerProvider', function(controllerProvider) { app_cached_providers.$controllerProvider = controllerProvider; } ]); 

    Как мы видим, мы просто создали приложение «приложение», а также создали держатель app_cached_providers (после стиля angularAMD) . В фазе конфигурации мы запрашиваем угловое значение для $controllerProvider и сохраняем ссылку на него.

    Теперь давайте продолжим в script.js :

     // III. inline dependency expression app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { $urlRouterProvider .otherwise("/home"); $stateProvider .state("home", { url: "/home", template: "
    this is home - not lazily loaded
    " }); $stateProvider .state("other", { url: "/other", template: "
    The message from ctrl: {{message}}
    ", controller: "OtherCtrl", resolve: { loadOtherCtrl: ["$q", function($q) { var deferred = $q.defer(); require(["OtherCtrl"], function() { deferred.resolve(); }); return deferred.promise; }], }, }); } ]);

    Эта часть выше показывает декларацию двух состояний. Один из них – 'home' не стандартный, ленивый. Контроллер неявный, но может использоваться стандарт.

    Второй – это состояние с именем "other" которое задает неименованный вид ui-view="" . И здесь мы можем сначала увидеть, ленивый груз. Внутри решения (см. 🙂

    Разрешить

    Вы можете использовать решение, чтобы предоставить вашему controllerу контент или данные, которые являются обычными для состояния. Решение – это необязательная карта зависимостей, которая должна быть введена в controller.

    Если какая-либо из этих зависимостей является promiseм , они будут разрешены и преобразованы в значение до создания экземпляра controllerа и запускается событие $ stateChangeSuccess.

    В этом случае мы знаем, что controller (по его названию) будет искать в угловом репозитории после завершения решения:

     // this controller name will be searched - only once the resolve is finished controller: "OtherCtrl", // let's ask RequireJS resolve: { loadOtherCtrl: ["$q", function($q) { // wee need $q to wait var deferred = $q.defer(); // and make it resolved once require will load the file require(["OtherCtrl"], function() { deferred.resolve(); }); return deferred.promise; }], }, 

    Хорошо, теперь, как упоминалось выше, основной содержит этот псевдоним def

     // alias libraries paths paths: { ... "OtherCtrl" : "Controller_Other", 

    А это значит, что файл «Controller_Other.js» будет искать и загружать. Это его содержание, которое делает магию . Наиболее важным здесь является использование ранее кэшированной ссылки на $controllerProvider

     // content of the "Controller_Other.js" define(['app'], function (app) { // the Default Controller // is added into the 'app' module // lazily, and only once app_cached_providers .$controllerProvider .register('OtherCtrl', function ($scope) { $scope.message = "OtherCtrl"; }); }); 

    трюк не в использовании app.controller() но

    $controllerProvider.Register

    Служба $ controller используется Angular для создания новых controllerов. Этот провайдер позволяет зарегистрировать controller через метод register() .

    Наконец, есть еще одно определение состояния, с более суженным решением … попытайтесь сделать его более читаемым:

     // IV ... build the object with helper functions // then assign to state provider var loadController = function(controllerName) { return ["$q", function($q) { var deferred = $q.defer(); require([controllerName], function() {deferred.resolve(); }); return deferred.promise; }]; } app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { var index = { url: "/", views: { "topMenu": { template: "
    The message from ctrl: {{message}}
    ", controller: "TopMenuCtrl", }, "": { template: "
    The message from ctrl: {{message}}
    ", controller: "ContentCtrl", }, }, resolve : { }, }; index.resolve.loadTopMenuCtrl = loadController("TopMenuCtrl"); index.resolve.loadContentCtrl = loadController("ContentCtrl"); $stateProvider .state("index", index); }]);

    Выше мы видим, что мы разрешаем два controllerа для обоих / всех названных представлений этого состояния

    Вот и все. Каждый controller, определенный здесь

     paths: { "TopMenuCtrl": "Controller_TopMenu", "ContentCtrl": "Controller_Content", "OtherCtrl" : "Controller_Other", ... }, 

    будут загружены через решение и $controllerProvider – через RequireJS – лениво. Убедитесь, что все здесь

    Подобные вопросы и ответы: AngularAMD + ui-router + имя динамического controllerа?

    В одном проекте я использовал ленивую загрузку controllerов и должен вручную вызвать $ digest в области, чтобы она работала. Я полагаю, что это поведение не меняется с помощью ui-router. Вы попробовали это?

     define(['app'], function (app) { app.controller('TopMenuCtrl', ['$scope', function ($scope) { $scope.message = "It works"; $scope.$digest(); }]); }); 
    Давайте будем гением компьютера.