重新打开并向已经引导的应用程序添加依赖项

时间:2013-09-18 14:58:54

标签: angularjs dependency-injection bootstrapping

有没有办法为已经引导的角度模块注入延迟依赖?这就是我的意思:

假设我有一个网站范围的角度应用,定义为:

// in app.js
var App = angular.module("App", []);

在每一页中:

<html ng-app="App">

稍后,我正在重新打开应用程序,根据当前页面的需要添加逻辑:

// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

现在,假设其中一个按需逻辑位也需要它们自己的依赖项(如ngTouchngAnimatengResource等)。如何将它们附加到基础应用程序?这似乎不起作用:

// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped

我意识到我可以事先做好一切,即 -

// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);

或者自己定义每个模块,然后将所有内容注入主应用程序(see here for more):

// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
  // ...
}])

// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])

但这需要我每次使用当前页面的依赖项初始化App。

我更喜欢在每个页面中包含基本app.js,只需向每个页面(reports.jshome.js等)引入所需的扩展,而无需每次都修改引导逻辑我添加或删除了一些东西。

当应用程序已经引导时,有没有办法引入依赖项?什么是惯用的方式(或方法)来做到这一点?我倾向于后一种解决方案,但想看看我描述的方式是否也可以完成。感谢。

6 个答案:

答案 0 :(得分:114)

我解决了这个问题:

再次引用该应用:

var app = angular.module('app');

然后将新需求推送到需求数组:

app.requires.push('newDependency');

答案 1 :(得分:12)

...简单 使用getter获取模块的实例,如下所示: var app = angular.module(“App”);

然后像这样添加到“requires”集合: app.requires [app.requires.length] =“ngResource”;

无论如何,这对我有用。祝你好运!

答案 2 :(得分:9)

根据this proposal on the Angular JS google group,此功能目前尚不存在。希望核心团队决定添加此功能,可以自己使用它。

答案 3 :(得分:4)

如果您希望一次添加多个依赖项,可以按如下方式传递它们:

<script>
    var app = angular.module('appName');
    app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>

答案 4 :(得分:4)

我意识到这是一个老问题,然而,还没有提供合适的答案,所以我决定分享我是如何解决的。

解决方案需要分支Angular,因此您不能再使用CDN了。然而,修改非常小,所以我很惊讶为什么Angular中不存在此功能。

我按照the link to google groups中提供的one of the other answers来解决此问题。在那里我找到了以下代码,它解决了这个问题:

instanceInjector.loadNewModules = function (mods) {
  forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};

当我将此代码添加到角度1.5.0源代码中的第4414行(createInjector函数内部,return instanceInjector;语句之前)时,它使我能够在引导之后添加依赖关系{ {1}}。

答案 5 :(得分:1)

从1.6.7版开始,现在可以使用$injector.loadNewModules([modules])引导应用程序后延迟加载模块。下面是从AngularJS文档中获取的示例:

app.factory('loadModule', function($injector) {
   return function loadModule(moduleName, bundleUrl) {
     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
   };
})

请阅读full documentation about loadNewModules,因为它周围有些陷阱。

还有一个很好的sample app by omkadiri与ui-router结合使用。