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


89

有没有办法向已经自举的角度模块注入后期依赖关系?这就是我的意思:

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

// 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', ...]);

或单独定义每个模块,然后将所有内容注入主应用程序(有关更多信息,请参见此处):

// 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.js在每一个页面,并简单介绍一下需要扩展到每个页面(reports.jshome.js,等),而无需修改引导逻辑每次我添加或删除一些东西。

当应用程序已经启动时,是否可以引入依赖项?什么被认为是惯用的方式?我倾向于后一种解决方案,但是想看看我描述的方法是否也可以完成。谢谢。


您能给我您的最终工作代码,看看吗?
Mangu Singh Rajpurohit15年

@ user2393267毫米,已经很久了,我不知道我是否还有该代码...对不起。我想我最终会重新设计,因为通常当我不得不修改某些东西时,这意味着我做错了……但是,如果您仍然决心采用这种方法,那么下面答案似乎是一个很好的指导。
sa125

Answers:


115

我这样解决了:

再次引用该应用程序:

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

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

app.requires.push('newDependency');

3
这对我来说是+1,我将它用于多个依赖项,例如app.requires.push('doctorCtrl','doctorService');
阿米尔2015年

8
这节省了我的架构。
Saeed Neamati 2015年

3
它对我不起作用。我正在按照说明动态添加依赖项,但是Angular仍然无法从添加的模块中找到服务。
Slava Fomin II

6
并且app.requires是一个数组,因此,如果要添加多个依赖项(如在Reports示例中),则可以将它们作为单独的参数传递给该push方法:app.requires.push('ui.event', 'ngResource');或者如果其他依赖项已经是数组:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
The Red Pea 2015年

2
有时我跳过投票,因为我不想登录,这次不是!谢谢!
CularBytes's

12

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

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

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


4
那对我有用!我有一个问题-为什么不使用:app.requires.push(“ ngResource”)?
Philipp Munin


4

如果您希望一次添加多个依赖项,则可以按如下所示通过push传递它们:

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

4

我意识到这是一个古老的问题,但是尚未提供有效的答案,因此我决定分享解决方法。

该解决方案需要分叉Angular,因此您不能再使用CDN。但是修改很小,所以令我惊讶的是为什么Angular中不存在此功能。

点击了该问题的其他答案之一中提供的Google网上论坛链接。在那里,我找到了以下代码,解决了该问题:

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

当我将此代码添加到有角度的1.5.0源代码中的4414行时(在createInjector函数内部,在return instanceInjector;语句之前),它使我能够在这样的引导之后添加依赖项$injector.loadNewModules(['ngCookies']);


投票最多的答案有什么问题(截至2017年6月26日)?看来是在您发布此消息一年多前提供的; 你的答案有什么优势吗?
红豌豆

@TheRedPea嗯,这没什么问题,只不过它不能解决我的问题,但是这个答案可以了
tjespe

它对您没有用,因为我想您已经将应用程序引导了?我也观察到了……
红豌豆

2
阅读链接的Google社区文章后,我什至更确定引导程序是需要这种解决方案的原因。因为最初的问题询问了一个“已经启动的应用程序”,所以没人支持(事实上,OP可能已经误传了)
Red Pea

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]); });
   };
})

请阅读有关loadNewModules的完整文档,因为周围有一些陷阱。

omkadiri还有一个非常好的示例应用程序,它与ui-router 一起使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.