什么"东西"可以注入其他人Angular.js? [英] What "things" can be injected into others in Angular.js?
问题描述
我有一点很难理解的角度依赖性注入。所以我的问题是,任何人都可以解释其中的类型,如控制器,工厂,供应商等,我们才能继续注入其他人,包括相同的类型的其他实例?
什么实际上,我找的就是这台充满着Y / N。对于具有相同的行/列的单元,这意味着一类型的值注入另一个另一个具有相同的类型
<$p$p><$c$c>+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+|我们可以注入? |恒|控制器|指令|厂|过滤器|供应商|服务|值|
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
|恒| | | | | | | | |
|控制器| | | | | | | | |
|指令| | | | | | | | |
|厂| | | | | | | | |
|过滤器| | | | | | | | |
|供应商| | | | | | | | |
|服务| | | | | | | | |
|值| | | | | | | | |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
而刚刚填写表是和否没有解释,我将进入多一点点的细节。
【注意事项,完成后说:这结束了......比我预期的相当长的时间。有一个TL;博士在底部,但我希望这证明信息]
[这个答案也已经加入到AngularJS维基:理解依赖注入 ]
的提供商( $提供
)
的 $提供
服务负责告诉角度如何创建新的可注射的东西;这些东西被称为服务。服务是由东西叫做提供,这是当你使用 $提供
你要创建的定义。定义提供通过提供商完成的
在 $提供
服务方法,你可以得到的保持 $按要求它提供
服务被注入到应用程序的配置
功能。一个例子可能是这样的:
的app.config(函数($提供){
$ provide.provider('问候',函数(){
这一点。$ GET =功能(){
复位功能(名称){
警报(你好,+姓名);
};
};
});
});
在这里我们定义了一个名为服务问候
新的供应商;我们可以注入一个名为问候变量
到任何注射功能(如控制器,后来更多)和角度将调用提供商的 $ GET
,以便返回该服务的新实例功能。在这种情况下,将被注入的东西是一个函数,它接受一个名称
参数和警报
SA消息,基于名字。我们可能会使用这样的:
app.controller('MainController',函数($范围,贺卡){
$ scope.onClick =功能(){
问候语(福特prefect');
};
});
现在,这里的窍门。 工厂
,服务
和值
都只是快捷方式来定义一个供应商的各个部分 - 也就是说,它们提供定义提供程序,而不必输入所有的东西出来的一种手段。例如,您可以编写的完全相同的提供商就像这样:
的app.config(函数($提供){
$ provide.factory('问候',函数(){
复位功能(名称){
警报(你好,+姓名);
};
});
});
要了解这一点很重要,所以我会另一种方式:在引擎盖下,AngularJS呼吁在完全相同的code ,我们写的上方( $提供。供应商
版本)的为的我们。有从字面上看,100%,在两个版本没有什么区别。 值
工作只是以同样的方式 - 如果无论我们会从我们的 $ GET
函数返回(即我们的工厂
功能)始终是完全一样的,我们可以用值
写的就更少了code。例如,因为我们总是回到我们的问候
服务相同的功能,我们可以使用值
来定义它,太
的app.config(函数($提供){
$ provide.value('问候',函数(名称){
警报(你好,+姓名);
});
});
再次,这是100%相同,我们使用定义此功能的其他两种方法 - 它只是一个方法来节省一些打字
。现在你可能注意到了这恼人的的app.config(函数($提供){...})
我一直在使用的东西。自定义新的供应商(通过的任何的上面给出的方法)是如此普遍,AngularJS公开 $提供商直接在模块对象
方法,以节省更多的打字:
VAR myMod = angular.module('Mymodule中',[]);myMod.provider(问候语,...);
myMod.factory(问候语,...);
myMod.value(问候语,...);
这些都为做了更详细的的app.config(...)
版本中,我们使用previously同样的事情。
的模式注射到目前为止,我已经跳过是恒
。就目前而言,这是很容易的说,它的工作原理就像值
。我们会看到有一个区别更高版本。
要查看 所有的这些作品code的都在做的确切的同样的事情:
myMod.provider('问候',函数(){
这一点。$ GET =功能(){
复位功能(名称){
警报(你好,+姓名);
};
};
});myMod.factory('问候',函数(){
复位功能(名称){
警报(你好,+姓名);
};
});myMod.value('问候',函数(名称){
警报(你好,+姓名);
});
注射器( $注射器
)
喷油器负责通过 $实际上是创建使用我们提供的code我们的服务实例提供
(没有双关语意)。你写一个函数,参数注入任何时候,你看到工作中的喷油器。每个AngularJS应用程序有一个 $注射器
,获取应用程序首次启动时创建的;你可以通过注入获得它的持有 $注射器
到任何注射功能(是的, $注射器
知道如何注入本身!)
一旦你有了 $注射器
,您可以通过调用 GET
上它得到一个定义服务的一个实例该服务的名称。例如,
VAR问候= $ injector.get('问候');
问候语(福特prefect');
注射器还负责注射服务纳入功能;例如,你可以神奇地中注入服务的功能,你使用注射器的引用
方法;
VAR myFunction的=功能(贺卡){
问候语(福特prefect');
};
$ injector.invoke(myFunction的);
其值得注意的是,喷油器将只创建一个服务的一次的实例。然后,它缓存无论该服务的名称的提供回报;接下来你问的服务的时候,你就会得到完全相同的对象。
因此,要回答你的问题,你可以注入到服务被称为与 $ injector.invoke
任何函数。这包括
- 控制器定义功能
- 指令定义功能
- 过滤器定义功能
- 提供的
$ GET
方法(又名工厂
定义函数)
由于恒
和值
总是返回一个静态值,他们不是通过喷油器调用,因此,你不能用任何东西,然后注入。
配置提供商
您可能想知道为什么会有人打扰建立一个完整的供应商与提供
方法,如果工厂
,值
等都是容易得多。答案是,提供商允许很多的配置。我们已经提到,当你创建通过提供商的服务(或任何角度的快捷方式给你),你创建一个新的供应商,它定义了服务是如何构建。我的什么也没有的一提的是,这些供应商可以注入配置
应用程序的部分,以便你可以与他们进行互动!
首先,角运行应用程序在两个阶段 - 对配置
和运行
阶段。在配置
阶段,正如我们所看到的,在这里你可以设置任何供应商是必要的。这也是指令,控制器,过滤器等得到成立。在运行
阶段,您可能已经猜到,就是角实际上编译你的DOM并启动您的应用程序。
您可以添加额外的code在这些阶段与 myMod.config
和 myMod.run $ C $要运行C>功能 - 每次取一个函数过程中特定阶段运行。正如我们在第一部分看到,这些功能是可注射 - 我们我们的第一个code样品中注入内置
模块 - $提供
服务。然而,值得一提的是,在配置
阶段,只有供应商可以注入(适用的服务在<$ C $异常C> AUTO $提供
和 $注射器
)
例如,下面就是不允许
myMod.config(功能(贺卡){
//将无法正常工作 - 问候是服务的一个实例* *。
//只为服务供应商可以在配置块被注入。
});
您的做什么的访问是任何的提供商的服务为您所做的:
myMod.config(功能(greetingProvider){
// 一个OK!
});
有一个重要的例外:恒
S,因为它们不能被改变,被允许在配置
块(这是他们从值
S)。他们只以他们的名字(无需提供
后缀)进行访问。
当你为服务定义的提供商,该提供商被命名为的ServiceProvider
,其中服务
是名称服务。现在我们可以使用供应商的力量做做一些更复杂的东西!
myMod.provider('问候',函数(){
变种文字=你好,; this.setText =功能(值){
文本=价值;
}; 这一点。$ GET =功能(){
复位功能(名称){
警报(文本+名);
};
};
});myMod.config(功能(greetingProvider){
greetingProvider.setText(你好那里);
});myMod.run(功能(贺卡){
问候语(福特prefect');
});
现在,我们对我们的供应商叫的setText
,我们可以用它来定制我们警报
函数;我们可以访问该提供商在配置
阻塞调用此方法和定制服务。当我们终于运行我们的应用程序,我们可以抢问候
服务,并尝试一下,看看我们的定制生效。
由于这是一个更为复杂的例子,这里有一个工作演示: http://jsfiddle.net/BinaryMuse/9GjYg/
控制器( $控制器
)
控制器的功能可以注入,但控制器本身不能被注入到其他的事情。这是因为控制器不通过提供程序创建。取而代之的是 $控制器
称为内置角服务,是负责设置你的控制器。当你调用 myMod.controller(...)
,你实际上访问的这个服务的提供商,就像在最后一节。
例如,当你定义一个控制器是这样的:
myMod.controller('MainController',函数($范围){
// ...
});
你实际上做的是这样的:
myMod.config(函数($ controllerProvider){
$ controllerProvider.register('MainController',函数($范围){
// ...
});
});
后来,当角需要创建控制器的一个实例,它使用了 $控制器
服务(这反过来又使用了 $注射器
来调用您的控制器功能,因此它会注入其依赖太)。
过滤器和指令
过滤器
和指令
工作完全相同的方式为控制器
; 过滤器
使用了一个名为 $过滤器
服务及其提供者 $ filterProvider
,而指令
使用一个名为服务 $编译
及其供应商 $ compileProvider
。有些链接:
- $过滤器: http://docs.angularjs.org/api/ng.$filter
- $ filterProvider:<一href=\"http://docs.angularjs.org/api/ng.%24filterProvider\">http://docs.angularjs.org/api/ng.$filterProvider
- $编译:<一href=\"http://docs.angularjs.org/api/ng.%24compile\">http://docs.angularjs.org/api/ng.$compile
- $ compileProvider:<一href=\"http://docs.angularjs.org/api/ng.%24compileProvider\">http://docs.angularjs.org/api/ng.$compileProvider
按照其他的例子, myMod.filter
和 myMod.directive
的快捷键来配置这些服务。
因此,要总结,这被称为与 $ injector.invoke
任意功能的可注入。这包括,从图表(但不限于):
- 控制器
- 指令
- 工厂
- 过滤器
- 提供商
$ GET
(定义为提供对象时) - 提供商功能(定义提供商作为构造函数时)
- 服务
提供商创造新的服务的可以注入的东西。这包括:
- 恒
- 工厂
- 提供商
- 服务
- 值
这是说,内置的服务,如 $控制器
和 $过滤器
的可以的被注入,并且可以的使用的那些服务,让您与这些方法(即使你定义的东西都没有,自己定义的新的过滤器和控制器的举行,能够注入的东西)。
除此之外,任何喷油器调用的功能,可以与任何供应商提供的服务注入 - 没有限制(除了配置
和<$ C $其他C>运行本文列出的差异)。
I'm having a little hard time understanding Dependency Injection in Angular. So my question is, can anyone explain which of the "types", like Controller, Factory, Provider, etc can we inject into others, including other instances of same "type"?
What I'm actually looking for is this table filled with y/n. For cells with same row/column, that means injecting the value of one "type" into another another one with the same "type"
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Can we inject? | Constant | Controller | Directive | Factory | Filter | Provider | Service | Value |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
| Constant | | | | | | | | |
| Controller | | | | | | | | |
| Directive | | | | | | | | |
| Factory | | | | | | | | |
| Filter | | | | | | | | |
| Provider | | | | | | | | |
| Service | | | | | | | | |
| Value | | | | | | | | |
+----------------+----------+------------+-----------+---------+--------+----------+---------+-------+
Rather that just fill in the table with "yes" and "no" with no explanation, I'll go into a little bit more detail.
[Note, added after finishing: this ended up being... quite a bit longer than I expected. There's a tl;dr at the bottom, but I hope this proves informational.]
[This answer has also been added to the AngularJS wiki: Understanding Dependency Injection]
The Provider ($provide
)
The $provide
service is responsible for telling Angular how to create new injectable things; these things are called services. Services are defined by things called providers, which is what you're creating when you use $provide
. Defining a provider is done via the provider
method on the $provide
service, and you can get hold of the $provide
service by asking for it to be injected into an application's config
function. An example might be something like this:
app.config(function($provide) {
$provide.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
});
Here we've defined a new provider for a service called greeting
; we can inject a variable named greeting
into any injectable function (like controllers, more on that later) and Angular will call the provider's $get
function in order to return a new instance of the service. In this case, the thing that will be injected is a function that takes a name
parameter and alert
s a message based on the name. We might use it like this:
app.controller('MainController', function($scope, greeting) {
$scope.onClick = function() {
greeting('Ford Prefect');
};
});
Now here's the trick. factory
, service
, and value
are all just shortcuts to define various parts of a provider--that is, they provide a means of defining a provider without having to type all that stuff out. For example, you could write that exact same provider just like this:
app.config(function($provide) {
$provide.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
});
It's important to understand, so I'll rephrase: under the hood, AngularJS is calling the exact same code that we wrote above (the $provide.provider
version) for us. There is literally, 100% no difference in the two versions. value
works just the same way--if whatever we would return from our $get
function (aka our factory
function) is always exactly the same, we can write even less code using value
. For example, since we always return the same function for our greeting
service, we can use value
to define it, too:
app.config(function($provide) {
$provide.value('greeting', function(name) {
alert("Hello, " + name);
});
});
Again, this is 100% identical to the other two methods we've used to define this function--it's just a way to save some typing.
Now you probably noticed this annoying app.config(function($provide) { ... })
thing I've been using. Since defining new providers (via any of the given methods above) is so common, AngularJS exposes the $provider
methods directly on the module object, to save even more typing:
var myMod = angular.module('myModule', []);
myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);
These all do the same thing as the more verbose app.config(...)
versions we used previously.
The one injectable I've skipped so far is constant
. For now, it's easy enough to say that it works just like value
. We'll see there's one difference later.
To review, all these pieces of code are doing the exact same thing:
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);
});
The Injector ($injector
)
The injector is responsible for actually creating instances of our services using the code we provided via $provide
(no pun intended). Any time you write a function that takes injected arguments, you're seeing the injector at work. Each AngularJS application has a single $injector
that gets created when the application first starts; you can get a hold of it by injecting $injector
into any injectable function (yes, $injector
knows how to inject itself!)
Once you have $injector
, you can get an instance of a defined service by calling get
on it with the name of the service. For example,
var greeting = $injector.get('greeting');
greeting('Ford Prefect');
The injector is also responsible for injecting services into functions; for example, you can magically inject services into any function you have using the injector's invoke
method;
var myFunction = function(greeting) {
greeting('Ford Prefect');
};
$injector.invoke(myFunction);
Its worth noting that the injector will only create an instance of a service once. It then caches whatever the provider returns by the service's name; the next time you ask for the service, you'll actually get the exact same object.
So, to answer your question, you can inject services into any function that is called with $injector.invoke
. This includes
- controller definition functions
- directive definition functions
- filter definition functions
- the
$get
methods of providers (aka thefactory
definition functions)
Since constant
s and value
s always return a static value, they are not invoked via the injector, and thus you cannot inject then with anything.
Configuring Providers
You may be wondering why anyone would bother to set up a full-fledged provider with the provide
method if factory
, value
, etc. are so much easier. The answer is that providers allow a lot of configuration. We've already mentioned that when you create a service via the provider (or any of the shortcuts Angular gives you), you create a new provider that defines how that service is constructed. What I didn't mention is that these providers can be injected into config
sections of your application so you can interact with them!
First, Angular runs your application in two-phases--the config
and run
phases. The config
phase, as we've seen, is where you can set up any providers as necessary. This is also where directives, controllers, filters, and the like get set up. The run
phase, as you might guess, is where Angular actually compiles your DOM and starts up your app.
You can add additional code to be run in these phases with the myMod.config
and myMod.run
functions--each take a function to run during that specific phase. As we saw in the first section, these functions are injectable--we injected the built-in $provide
service in our very first code sample. However, what's worth noting is that during the config
phase, only providers can be injected (with the exception of the services in the AUTO
module--$provide
and $injector
).
For example, the following is not allowed:
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
What you do have access to are any providers for services you've made:
myMod.config(function(greetingProvider) {
// a-ok!
});
There is one important exception: constant
s, since they cannot be changed, are allowed to be injected inside config
blocks (this is how they differ from value
s). They are accessed by their name alone (no Provider
suffix necessary).
Whenever you defined a provider for a service, that provider gets named serviceProvider
, where service
is the name of the service. Now we can use the power of providers do do some more complicated stuff!
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');
});
Now we have a function on our provider called setText
that we can use to customize our alert
; we can get access to this provider in a config
block to call this method and customize the service. When we finally run our app, we can grab the greeting
service, and try it out to see that our customization took effect.
Since this is a more complex example, here's a working demonstration: http://jsfiddle.net/BinaryMuse/9GjYg/
Controllers ($controller
)
Controller functions can be injected into, but controllers themselves can't be injected into other things. That's because controllers aren't created via the provider. Instead, there is a built-in Angular service called $controller
that is responsible for setting up your controllers. When you call myMod.controller(...)
, you're actually accessing this service's provider, just like in the last section.
For example, when you define a controller like this:
myMod.controller('MainController', function($scope) {
// ...
});
What you're actually doing is this:
myMod.config(function($controllerProvider) {
$controllerProvider.register('MainController', function($scope) {
// ...
});
});
Later, when Angular needs to create an instance of your controller, it uses the $controller
service (which in turn uses the $injector
to invoke your controller function so it gets its dependencies injected too).
Filters and Directives
filter
and directive
work exactly the same way as controller
; filter
uses a service called $filter
and its provider $filterProvider
, while directive
uses a service called $compile
and its provider $compileProvider
. Some links:
- $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
As per the other examples, myMod.filter
and myMod.directive
are shortcuts to configuring these services.
So, to summarize, any function that gets called with $injector.invoke
can be injected into. This includes, from your chart (but is not limited to):
- controller
- directive
- factory
- filter
- provider
$get
(when defining provider as an object) - provider function (when defining provider as a constructor function)
- service
The provider creates new services that can be injected into things. This includes:
- constant
- factory
- provider
- service
- value
That said, built-in services like $controller
and $filter
can be injected, and you can use those service to get hold of the new filters and controllers you defined with those methods (even though the things you defined aren't, by themselves, able to be injected into things).
Other than that, any injector-invoked function can be injected with any provider-provided service--there is no restriction (other than the config
and run
differences listed herein).
这篇关于什么&QUOT;东西&QUOT;可以注入其他人Angular.js?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!