我实际寻找的是这个表填充y / n。对于具有相同行/列的单元格,这意味着将一个“类型”的值注入另一个具有相同“类型”
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+ | Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value | +----------------+----------+------------+-----------+---------+--------+----------+---------+-------+ | Constant | | | | | | | | | | Controller | | | | | | | | | | Directive | | | | | | | | | | Factory | | | | | | | | | | Filter | | | | | | | | | | Provider | | | | | | | | | | Service | | | | | | | | | | Value | | | | | | | | | +----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
[注意,完成后添加:这最终是…比我预期的更长。有一个tl; dr在底部,但我希望这证明了信息。]
[这个答案也被添加到AngularJS wiki:Understanding Dependency Injection]
提供商($provide
)
$ provide服务负责告诉Angular如何创建新的可注入的东西;这些东西被称为服务。服务由称为提供程序的东西定义,这是您在使用$ provide时创建的。定义一个提供者是通过$ provide服务的提供者方法来完成的,你可以通过要求它被注入到应用程序的配置函数中来获得$ provide服务。一个例子可能是这样的:
app.config(function($provide) { $provide.provider('greeting',function() { this.$get = function() { return function(name) { alert("Hello," + name); }; }; }); });
这里我们为一个叫greeting的服务定义了一个新的提供者。我们可以向任何可注入的函数注入一个名为greeting的变量(例如控制器,稍后会提到),Angular将调用提供者的$ get函数,以返回一个新的服务实例。在这种情况下,要注入的事情是一个函数,它接受一个名称参数并基于名称警告消息。我们可以这样使用它:
app.controller('MainController',function($scope,greeting) { $scope.onClick = function() { greeting('Ford Prefect'); }; });
现在这里的诀窍。工厂,服务和价值都只是快捷方式来定义提供者的各个部分 – 也就是说,它们提供了一种定义提供者的方法,而不必键入所有的东西。例如,你可以这样写同样的提供者:
app.config(function($provide) { $provide.factory('greeting',function() { return function(name) { alert("Hello," + name); }; }); });
重要的是要理解,所以我将改写:在引擎盖下,AngularJS调用与我们上面写的完全相同的代码($ provide.provider版本)为我们。有字面上,100%没有区别在两个版本。值工作方式相同 – 如果我们从$ get函数(也就是我们的工厂函数)返回的总是完全相同的,我们可以使用值写更少的代码。例如,因为我们总是为我们的问候服务返回相同的函数,我们可以使用值来定义它:
app.config(function($provide) { $provide.value('greeting',function(name) { alert("Hello," + name); }); });
同样,这是与我们用来定义这个函数的其他两个方法100%相同 – 这只是一个保存一些类型的方法。
现在你可能注意到这个烦人的app.config(function($ provide){…})我一直在使用的东西。由于定义新的提供者(通过上面给定的方法)是如此常见,AngularJS直接暴露$ provider方法对模块对象,以节省更多的输入:
var myMod = angular.module('myModule',[]); myMod.provider("greeting",...); myMod.factory("greeting",...); myMod.value("greeting",...);
这些都做同样的事情,我们以前使用更详细的app.config(…)版本。
到目前为止,我跳过的一个注射器是不变的。现在,它很容易说,它的工作原理就像价值。我们会看到稍后有一个区别。
回顾一下,所有这些代码都是做同样的事情:
myMod.provider('greeting',function() { this.$get = function() { return function(name) { alert("Hello," + name); }; }; }); myMod.factory('greeting',function() { return function(name) { alert("Hello," + name); }; }); myMod.value('greeting',function(name) { alert("Hello," + name); });
注射器($injector
)
注入器负责使用我们通过$ provide提供的代码实际创建我们的服务实例(不需要双关)。任何时候你写一个函数接受注入的参数,你看到注入器在工作。每个AngularJS应用程序都有一个$ inject,当应用程序首次启动时创建;你可以通过注入$ injector注入任何注入函数(是的,注入$知道如何注入自己!)。
一旦你有$ injector,你可以获得一个定义的服务的实例,通过使用服务的名称调用get。例如,
var greeting = $injector.get('greeting'); greeting('Ford Prefect');
注射器还负责将服务注入功能;例如,您可以将服务注入到使用注入器的invoke方法的任何函数中;
var myFunction = function(greeting) { greeting('Ford Prefect'); }; $injector.invoke(myFunction);
值得注意的是,注入器只会创建一次服务的实例。然后它缓存提供程序返回的任何服务的名称;下次你请求服务时,你实际上会得到完全相同的对象。
所以,为了回答你的问题,你可以注入服务到用$ injector.invoke调用的任何函数。这包括
>控制器定义函数
>指令定义函数
>过滤器定义函数
>提供程序的$ get方法(也称为工厂定义函数)
因为常量和值总是返回一个静态值,它们不通过注入器调用,因此你不能注入任何东西。
配置提供程序
你可能会想知道为什么任何人都会麻烦使用提供方法设置一个完整的提供程序,如果工厂,价值等等容易得多。答案是提供商允许很多配置。我们已经提到,当您通过提供者(或者Angular提供的任何一个快捷方式)创建服务时,您可以创建一个新的提供者来定义该服务的构造方式。我没有提到的是,这些提供程序可以注入到应用程序的配置部分,以便您可以与他们交互!
首先,Angular在两个阶段运行你的应用程序 – 配置和运行阶段。如我们所见,配置阶段是您可以根据需要设置任何提供程序的位置。这也是指令,控制器,过滤器等设置的地方。运行阶段,你可能猜到,Angular实际上编译你的DOM和启动你的应用程序。
您可以使用myMod.config和myMod.run函数添加要在这些阶段中运行的其他代码 – 每个函数都会在该特定阶段运行一个函数。正如我们在第一部分中看到的,这些函数是可注入的 – 我们在第一个代码示例中注入了内置的$ provide服务。然而,值得注意的是,在配置阶段,只有提供者可以注入(除了AUTO模块中的服务 – $ provide和$ injector)。
例如,不允许以下操作:
myMod.config(function(greeting) { // WON'T WORK -- greeting is an *instance* of a service. // Only providers for services can be injected in config blocks. });
您可以访问的是您提供的服务的任何提供商:
myMod.config(function(greetingProvider) { // a-ok! });
有一个重要的例外:常量,因为它们不能被改变,允许被注入到配置块中(这是它们与值的不同)。它们仅通过其名称访问(不需要提供程序后缀)。
无论何时为服务定义了提供程序,该提供程序都将获得名为serviceProvider,其中service是服务的名称。现在我们可以使用提供商的力量做一些更复杂的东西!
myMod.provider('greeting',function() { var text = 'Hello,'; this.setText = function(value) { text = value; }; this.$get = function() { return function(name) { alert(text + name); }; }; }); myMod.config(function(greetingProvider) { greetingProvider.setText("Howdy there,"); }); myMod.run(function(greeting) { greeting('Ford Prefect'); });
现在我们在我们的提供程序上有一个名为setText的函数,我们可以使用它来自定义警报;我们可以在配置块中访问此提供程序以调用此方法并自定义服务。当我们终于运行我们的应用程序,我们可以抓住问候服务,并尝试看看我们的定制生效。
由于这是一个更复杂的例子,这里有一个工作示范:http://jsfiddle.net/BinaryMuse/9GjYg/
控制器($controller
)
控制器功能可以注入,但是控制器本身不能注入其他东西。这是因为控制器不是通过提供程序创建的。相反,有一个内置的Angular服务,称为$ controller,负责设置控制器。当你调用myMod.controller(…),你实际上访问this service’s provider,就像在上一节。
例如,当您定义如下所示的控制器时:
myMod.controller('MainController',function($scope) { // ... });
你实际做的是这样的:
myMod.config(function($controllerProvider) { $controllerProvider.register('MainController',function($scope) { // ... }); });
后来,当Angular需要创建一个你的控制器的实例,它使用$ controller服务(反过来使用$ injector调用你的控制器函数,所以它得到它的依赖注入)。
过滤器和指令
过滤器和指令的工作方式与控制器完全相同;过滤器使用一个名为$ filter的服务及其提供者$ filterProvider,而指令使用一个名为$ compile的服务及其提供者$ compileProvider。一些链接:
> $ filter:http://docs.angularjs.org/api/ng.$filter
> $ filterProvider:http://docs.angularjs.org/api/ng.$filterProvider
> $ compile:http://docs.angularjs.org/api/ng.$compile
> $ compileProvider:http://docs.angularjs.org/api/ng.$compileProvider
根据其他示例,myMod.filter和myMod.directive是配置这些服务的快捷方式。
所以,总结一下,使用$ injector.invoke调用的任何函数都可以注入。这包括,从您的图表(但不限于):
>控制器
>指令
>工厂
>过滤器
> provider $ get(将provider定义为对象时)
>提供者函数(当将提供者定义为构造函数时)
>服务
提供者创建可以注入事物的新服务。这包括:
>常数
>工厂
>提供商
>服务
>值
也就是说,内置的服务像$ controller和$ filter可以被注入,你可以使用这些服务来获取你用这些方法定义的新的过滤器和控制器(即使你定义的东西本身不是,能够注入到事物中)。