Ответ 1
Нет, это официально не поддерживается на данный момент. Все модули должны быть загружены в браузер (и объявлены как зависимость основного модуля приложения) до того, как приложение AngularJS будет загружено.
Я не использую angular для одностраничного приложения, но я хотел бы определить основной модуль приложения один раз из-за проблем с загрузкой. В то же время я хотел бы вводить/требовать модули на основе каждой страницы, а не одеяло, поскольку не все файлы JS будут загружены на каждую страницу.
Могу ли я определить приложение без необходимых модулей:
app = angular.module( "app", [])
и вводите ли они их из контроллера или на более поздней стадии?
Нет, это официально не поддерживается на данный момент. Все модули должны быть загружены в браузер (и объявлены как зависимость основного модуля приложения) до того, как приложение AngularJS будет загружено.
Сверху моей головы, прочитав свой вопрос, я могу думать о возможном решении/взломе.
Идея заключалась бы в определении массива зависимостей перед включением любых модулей и добавлении к ним в каждом модуле:
// before anything else
window.loadedDependencies = [];
// at the end of each module file:
window.loadedDependencies.push('moduleName')
// after all that, at the app definition:
app = angular.module("app", loadedDependencies)
Честно говоря, я действительно не рассматривал какие-либо последствия/осложнения, которые этот метод может подразумевать, и я не могу не ручаться за это до тех пор, пока не сделаю (почему не так много вызовов для файлов script и кеширования хороших для вашего случая использования?)
Используя отличную идею Tiago (повышайте его!), в моем модуле есть следующее:
window.dependencies = _.union(window.dependencies || [], [
"ngRoute",
"app.mymodule1"
]);
angular
.module("app.mymodule1", [])
.config(["$routeProvider", function ($routeProvider) {
// more code
}]);
и это в моем app.js
:
var app;
window.dependencies = _.union(window.dependencies || [], [
"ngRoute",
"app.anothermodule"
]);
window.app = app = angular.module("app", window.dependencies);
Я использую LoDash, поэтому я union зависимости для получения массива уникальных значений - некоторые из моих модулей используют те же зависимости, что и app.js
, например ngRoute
.
Мой script включает в себя нижнюю часть тега body
, как показано ниже:
<!-- scripts from other pages/modules included here -->
<script src="/js/anothermodule/anothermodule.js"></script>
<script src="/js/app.js"></script>
Работает как шарм!
Мои страницы разделяют страницу "master", но у меня есть определения модулей в их собственных файлах, поэтому мне нужно что-то вроде этого.
Мы можем достичь этого, используя app.requires
//app.js
var app = angular.module('myngapp',['ngRoute','ngCookies','ui.bootstrap','kendo.directives','pascalprecht.translate','tmh.dynamicLocale']);
app.config(['$routeProvider', '$httpProvider', '$translateProvider', 'tmhDynamicLocaleProvider', '$compileProvider', function($routeProvider, $httpProvider, $translateProvider, tmhDynamicLocaleProvider, $compileProvider) {
'use strict';
$compileProvider.debugInfoEnabled(false);
$routeProvider.otherwise({
redirectTo: '/login'
});
}]);
В myModule.js
app.requires.push('app.myModule');
и в вашем index.html, включите app.js
first и myModule.js
next. Таким образом, вы можете включить n количество модулей без изменения app.js
.
Включите myModule.js на лету из app.js
var mainHead = document.getElementsByTagName('HEAD').item(0);
var myScript= document.createElement("script");
myScript.type = "text/javascript";
mainHead.appendChild( myScript);
myScript.src='../myModule.js';
myScript.onload = function(){
angular.element(document).ready(function() {
angular.bootstrap(document, ['myngapp']);
});
}
Примечание: здесь мы вручную загружаем приложение так, чтобы динамически загружаемые модули также были включены в наше приложение
Я знаю, что это не очень красиво, но как сделать следующее:
var injectedDependencies = [.....];
angular.prevmodule = angular.module;
angular.module = function(name, params){
if(params){
params.push(injectedDependencies);
}
return angular.prevmodule.apply(angular, arguments);
}
edit: обратите внимание, что это полезно, если вы хотите вводить модули, не имея при этом приложения, чтобы знать их (для exapmple для ведения журнала, мониторинга, безопасности и т.д.), но не для того, чтобы вы захотели ввести инъекцию после того, как приложение было загружено.
Я борюсь с той же проблемой. Я думаю, http://blog.getelementsbyidea.com/load-a-module-on-demand-with-angularjs/ может делать то, что вы хотели.
В своем github https://github.com/ocombe/ocLazyLoad вы можете найти:
AppCtrl.js
https://github.com/ocombe/ocLazyLoad/blob/master/examples/example1/js/app.js#L24AppCtrl.js
позже загружает сетку https://github.com/ocombe/ocLazyLoad/blob/master/examples/example1/js/AppCtrl.js#L28 во время выполнения (и асинхронно)! voi'laЭто может показаться немного сложным, но если вы действительно заинтересованы в загрузке их во время выполнения, это может быть единственным решением, за исключением ручного modyfing _invokeQueue
вручную.