什么“东西"可以在 Angular.js 中注入其他人吗? [英] What "things" can be injected into others in Angular.js?

查看:22
本文介绍了什么“东西"可以在 Angular.js 中注入其他人吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解 Angular 中的依赖注入.所以我的问题是,谁能解释一下哪些类型",比如控制器、工厂、提供者等,我们可以注入到其他人中,包括相同类型"的其他实例?

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"?

我真正要找的是这张填满 y/n 的表格.对于具有相同行/列的单元格,这意味着将一种类型"的值注入另一种具有相同类型"的值

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.

[注意,完成后补充:这最终是……比我预期的要长得多.底部有一个 tl;dr,但我希望这能提供信息.]

[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.]

[此答案也已添加到 AngularJS wiki:理解依赖注入]

[This answer has also been added to the AngularJS wiki: Understanding Dependency Injection]

$provide 服务负责告诉 Angular 如何创建新的可注入的东西;这些东西被称为服务.服务由称为 providers 的东西定义,这是您在使用 $provide 时创建的内容.定义提供者是通过 $provide 服务上的 provider 方法完成的,你可以通过请求获得 $provide 服务注入到应用程序的 config 函数中.一个例子可能是这样的:

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

这里我们为一个名为 greeting 的服务定义了一个新的提供者;我们可以将一个名为 greeting 的变量注入任何可注入的函数(如控制器,稍后会详细介绍),Angular 将调用提供者的 $get 函数以返回一个新实例的服务.在这种情况下,将被注入的是一个函数,它接受一个 name 参数和 alert 基于名称的消息.我们可以这样使用它:

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 alerts a message based on the name. We might use it like this:

app.controller('MainController', function($scope, greeting) {
  $scope.onClick = function() {
    greeting('Ford Prefect');
  };
});

现在是诀窍. factoryservicevalue 都只是定义各个部分的快捷方式提供者——也就是说,它们提供了一种定义提供者的方法,而无需输入所有内容.例如,您可以像这样编写完全相同的提供程序:

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

理解这一点很重要,所以我会改写:在幕后,AngularJS 正在调用我们上面编写的完全相同的代码($provide.provider 版本) 为了我们.从字面上看,两个版本 100% 没有区别.value 以同样的方式工作——如果我们从 $get 函数(也就是我们的 factory 函数)返回的任何东西总是完全一样的,我们可以使用 value 编写更少的代码.例如,由于我们总是为 greeting 服务返回相同的函数,我们也可以使用 value 来定义它:

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

同样,这与我们用来定义此函数的其他两种方法 100% 相同——这只是一种节省输入的方法.

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.

现在您可能已经注意到我一直在使用的这个烦人的 app.config(function($provide) { ... }) 东西.由于定义新的提供者(通过上面给定的任何方法)是如此常见,AngularJS 直接在模块对象上公开 $provider 方法,以节省更多的输入:

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", ...);

这些都与我们之前使用的更详细的 app.config(...) 版本做同样的事情.

These all do the same thing as the more verbose app.config(...) versions we used previously.

到目前为止,我跳过的一个可注入代码是 constant.现在,很容易说它就像 value 一样工作.我们稍后会看到有一个区别.

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

注入器($injector)

注入器负责使用我们通过 $provide 提供的代码(没有双关语)实际创建我们的服务实例.任何时候你编写一个接受注入参数的函数时,你都会看到注入器在工作.每个 AngularJS 应用程序都有一个 $injector,它在应用程序第一次启动时被创建;你可以通过将 $injector 注入任何可注入函数来获得它(是的,$injector 知道如何注入自己!)

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!)

一旦你有了 $injector,你就可以通过使用服务的名称调用 get 来获取一个已定义服务的实例.例如,

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');

注入器还负责将服务注入到函数中;例如,您可以使用注入器的 invoke 方法神奇地将服务注入到您拥有的任何函数中;

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.

因此,为了回答您的问题,您可以将服务注入任何使用 $injector.invoke 调用的函数.这包括

So, to answer your question, you can inject services into any function that is called with $injector.invoke. This includes

  • 控制器定义函数
  • 指令定义函数
  • 过滤器定义函数
  • 提供者的 $get 方法(又名 factory 定义函数)
  • controller definition functions
  • directive definition functions
  • filter definition functions
  • the $get methods of providers (aka the factory definition functions)

由于 constants 和 values 总是返回一个静态值,它们不是通过注入器调用的,因此你不能用任何东西注入它们.

Since constants and values always return a static value, they are not invoked via the injector, and thus you cannot inject them with anything.

您可能想知道如果 factoryvalue 等,为什么有人会费心使用 provide 方法来设置成熟的提供程序. 容易多了.答案是提供者允许大量配置.我们已经提到,当您通过提供者(或 Angular 为您提供的任何快捷方式)创建服务时,您将创建一个新的提供者,该提供者定义了该服务的构造方式.我没有提到的是,这些提供程序可以注入到您的应用程序的config 部分,以便您可以与它们进行交互!

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!

首先,Angular 分两个阶段运行您的应用程序——configrun 阶段.正如我们所见,在 config 阶段,您可以根据需要设置任何提供程序.这也是设置指令、控制器、过滤器等的地方.正如您可能猜到的那样,run 阶段是 Angular 实际编译您的 DOM 并启动您的应用程序的地方.

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.

您可以使用 myMod.configmyMod.run 函数添加要在这些阶段运行的其他代码——每个函数都在该特定阶段运行一个函数.正如我们在第一节中看到的,这些函数是可注入的——我们在第一个代码示例中注入了内置的 $provide 服务.但是,值得注意的是,config阶段,只能注入提供者(AUTO模块中的服务除外--$provide$injector).

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).

例如,以下是不允许:

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

有一个重要的例外:constants,因为它们不能改变,所以被允许注入到 config 块中(这就是它们与 s).它们仅通过名称访问(不需要 Provider 后缀).

There is one important exception: constants, since they cannot be changed, are allowed to be injected inside config blocks (this is how they differ from values). They are accessed by their name alone (no Provider suffix necessary).

每当您为服务定义提供者时,该提供者都会被命名为 serviceProvider,其中 service 是服务的名称.现在我们可以利用提供者的力量做一些更复杂的事情!

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

现在我们的 provider 上有一个名为 setText 的函数,我们可以用它来自定义我们的 alert;我们可以在 config 块中访问此提供程序以调用此方法并自定义服务.当我们最终运行我们的应用程序时,我们可以获取 greeting 服务,并尝试看看我们的自定义是否生效.

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.

由于这是一个更复杂的例子,这里有一个工作演示:http://jsfiddle.net/BinaryMuse/9GjYg/

Since this is a more complex example, here's a working demonstration: http://jsfiddle.net/BinaryMuse/9GjYg/

控制器函数可以注入,但控制器本身不能注入其他东西.那是因为控制器不是通过提供者创建的.相反,有一个名为 $controller 的内置 Angular 服务负责设置您的控制器.当您调用 myMod.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) {
  // ...
});

你实际上在做什么:

myMod.config(function($controllerProvider) {
  $controllerProvider.register('MainController', function($scope) {
    // ...
  });
});

稍后,当 Angular 需要创建控制器的实例时,它会使用 $controller 服务(该服务又使用 $injector 来调用您的控制器函数,以便它也注入了它的依赖项).

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).

filterdirective 的工作方式与 controller 完全相同;filter 使用名为 $filter 的服务及其提供者 $filterProvider,而 directive 使用名为 的服务$compile 及其提供者 $compileProvider.一些链接:

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:

根据其他示例,myMod.filtermyMod.directive 是配置这些服务的快捷方式.

As per the other examples, myMod.filter and myMod.directive are shortcuts to configuring these services.

总而言之,任何使用 $injector.invoke 调用的函数都可以注入.这包括,从您的图表(但不限于):

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):

  • 控制器
  • 指令
  • 工厂
  • 过滤器
  • provider $get(将提供者定义为对象时)
  • provider 函数(当将 provider 定义为构造函数时)
  • 服务
  • 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:

  • 恒定
  • 工厂
  • 供应商
  • 服务
  • 价值

也就是说,可以注入$controller$filter 等内置服务,并且您可以使用em> 那些服务来获取你用这些方法定义的新过滤器和控制器(即使你定义的东西本身不能注入到东西中).

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).

除此之外,任何注入器调用的函数都可以与任何提供者提供的服务一起注入——没有限制(除了列出的 configrun 差异在此).

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).

这篇关于什么“东西"可以在 Angular.js 中注入其他人吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆