一般而言,您需要设备某种基础设施来声明依赖关系并抽象声明的服务或模块的实例化。
鉴于问题中的 Angular 示例,如果您退后一步思考一下,一切都是通过 Angular 中的 angular.module 函数发生的。
直观地说,这必须是如何在底层依赖注入容器中声明和注册“应用程序”以及应用程序的较小组件(指令、服务、控制器)。毕竟,所有这些都将一组依赖项作为第二个参数:
var injectable3, injectable2, injectable;
injectable = angular.module( 'myApp', [dependency, ..., fn(d1, ...){}]);
injectable2 = injectable.controller('foo', [dependency, ..., fn(d2, ...){}]);
injectable3 = injectable.service( 'bar', [dependency, ..., fn(d3, ...){}]);
看起来很神奇,但实际上并非如此。他们都通过某种依赖注入容器进行对话。这实际上是在cmet中说明的:loader.js
检查angular中的一些核心方法:
/**
* @name angular.bootstrap
* @returns {auto.$injector} Returns the newly created injector for app.
*/
function bootstrap(element, modules, config) {
// (...)
var doBootstrap = function(element, modules, config) {
modules = modules || [];
modules.unshift(['$provide', function ($provide) {
$provide.value('$rootElement', element);
}]);
if (config.debugInfoEnabled) {
modules.push(['$compileProvider', function ($compileProvider) {
$compileProvider.debugInfoEnabled(true);
}]);
}
// (...)
modules.unshift('ng');
var injector = createInjector(modules, config.strictDi);
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
function bootstrapApply(scope, element, compile, injector) {
scope.$apply(function () {
element.data('$injector', injector);
compile(element)(scope);
});
}]
);
return injector;
};
// (...)
if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
return doBootstrap();
}
// (...)
}
如果您不记得,引导方法负责初始化应用程序,例如<body ng-app="coffeeShop">。上面的摘录说明了为每个应用程序声明了额外的依赖项。下一步 (createInjector) 是找出依赖项的创建位置和方式。
总而言之,一种方法是声明提供者,使用定位器注册它们,然后声明依赖于提供者的模块,最后在稍后阶段引导整个事情。
我想这个星期天早上我已经吃饱了。