Angular.js 中哪些“东西”可以注入到其他东西中?

2023-11-23

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

我真正要找的是这张表,上面写满了 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 中:了解依赖注入]


提供者($provide)

The $provideservice 负责告诉 Angular 如何创建新的可注入事物;这些东西被称为services。服务是由称为提供者,这就是您使用时创建的内容$provide。定义提供者是通过provider方法上的$provide服务,您可以获取$provide通过要求将服务注入到应用程序的config功能。一个例子可能是这样的:

app.config(function($provide) {
  $provide.provider('greeting', function() {
    this.$get = function() {
      return function(name) {
        alert("Hello, " + name);
      };
    };
  });
});

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

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

现在这就是窍门。 factory, service, and value都是定义提供者各个部分的快捷方式——也就是说,它们提供了一种定义提供者的方法,而无需键入所有内容。例如,你可以这样写完全相同的提供商像这样:

app.config(function($provide) {
  $provide.factory('greeting', function() {
    return function(name) {
      alert("Hello, " + name);
    };
  });
});

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

app.config(function($provide) {
  $provide.value('greeting', function(name) {
    alert("Hello, " + name);
  });
});

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

现在你可能注意到这很烦人app.config(function($provide) { ... })我一直在用的东西。自从定义新的提供商(通过any上面给定的方法)是如此常见,AngularJS 公开了$provider直接在模块对象上使用方法,以节省更多的输入:

var myMod = angular.module('myModule', []);

myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);

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

到目前为止我跳过的一种注射剂是constant。现在,很容易说它的工作原理就像value。稍后我们会看到其中有一个区别。

回顾, all这些代码正在执行exact一样:

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知道如何自我注入!)

一旦你有$injector,您可以通过调用来获取已定义服务的实例get上面有服务的名称。例如,

var greeting = $injector.get('greeting');
greeting('Ford Prefect');

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

var myFunction = function(greeting) {
  greeting('Ford Prefect');
};
$injector.invoke(myFunction);

值得注意的是,注入器只会创建服务的实例once。然后它会缓存提供者通过服务名称返回的任何内容;下次您请求服务时,您实际上会得到完全相同的对象。

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

  • 控制器定义函数
  • 指令定义函数
  • 过滤器定义函数
  • the $get提供者的方法(又名factory定义函数)

Since constants and values 总是返回一个静态值,它们不是通过注入器调用的,因此你不能向它们注入任何东西。

配置提供者

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

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

您可以使用以下命令添加要在这些阶段运行的其他代码myMod.config and myMod.run函数——每个函数都在该特定阶段运行一个函数。正如我们在第一节中看到的,这些函数是可注入的——我们注入了内置函数$provide我们第一个代码示例中的服务。不过,值得注意的是在此期间config阶段,只能注入提供者(以下服务除外)AUTO模块 -$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.
});

你什么do可以访问任何提供者对于您所做的服务:

myMod.config(function(greetingProvider) {
  // a-ok!
});

有一个重要的例外:constant由于无法更改,因此允许注入到内部config块(这就是它们与values)。仅通过名称即可访问它们(无Provider必要的后缀)。

每当您为服务定义提供者时,该提供者都会被命名serviceProvider, where 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我们可以用它来定制我们的alert;我们可以通过以下方式访问该提供商config阻止调用此方法并自定义服务。当我们最终运行我们的应用程序时,我们可以获取greeting服务,试一试,我们的定制生效了。

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

控制器($controller)

控制器函数可以被注入,但控制器本身不能被注入到其他东西中。这是因为控制器不是通过提供者创建的。相反,有一个内置的 Angular 服务,称为$controller负责设置您的控制器。你打电话时myMod.controller(...),你实际上正在访问该服务的提供者,就像上一节一样。

例如,当您定义这样的控制器时:

myMod.controller('MainController', function($scope) {
  // ...
});

你实际上在做的是这样的:

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

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

过滤器和指令

filter and directive工作方式与controller; filter使用名为的服务$filter及其提供者$filterProvider, while directive使用名为的服务$compile及其提供者$compileProvider。一些链接:

  • $过滤器:https://docs.angularjs.org/api/ng/service/$filter
  • $filterProvider:https://docs.angularjs.org/api/ng/provider/$filterProvider
  • $编译:https://docs.angularjs.org/api/ng/service/$compile
  • $compileProvider:https://docs.angularjs.org/api/ng/provider/$compileProvider

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


tl;dr

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

  • 控制器
  • 指示
  • factory
  • filter
  • 提供者$get(将提供者定义为对象时)
  • 提供程序函数(将提供程序定义为构造函数时)
  • service

提供商创建新服务可以注入到东西中。这包括:

  • constant
  • factory
  • provider
  • service
  • value

也就是说,内置服务如$controller and $filter can被注射,你可以use这些服务来获取您使用这些方法定义的新过滤器和控制器(即使您定义的事物本身无法注入事物中)。

除此之外,任何注入器调用的函数都可以注入任何提供者提供的服务——没有任何限制(除了config and run此处列出的差异)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Angular.js 中哪些“东西”可以注入到其他东西中? 的相关文章

随机推荐

  • 仅向网站用户显示 YouTube 私人视频

    我有使用 YouTube API 的经验 但我总是用它来拍摄公共视频 现在 我想要实现的是 使我的 YouTube 频道上的视频完全不可见 换句话说 是私有的 并且仅向网站用户显示该视频 这可能吗 如何实现 这是来自Google 产品论坛
  • ios 中检测 SIM 卡的可能方法?

    我有一个能够发送消息的 iPhone 应用程序 我想在 iPhone 中没有 SIM 卡时提醒用户 所以我尝试了以下三个功能来检查SIM卡可用性 Class messageClass NSClassFromString MFMessageC
  • style 属性不使用 android: 命名空间前缀的原因

    在Android中 style属性不使用android 命名空间前缀的原因是什么 See how style不开始于android 有人知道为什么吗
  • 用于编译node_modules中模块的Webpack配置

    我的 webpack babel 配置有问题 我已经将我的组件存储库 内部没有 webpack 配置的 es6 模块 安装为 node module 在这种情况下它不起作用 我收到 意外的令牌导入 错误 babel 不转译 es6 代码 但
  • 在 android 中扩展简单的 xml 布局时出现内存不足错误

    我在 google play 上遇到了一些用户报告的内存错误 无论我如何努力 我似乎 都无法重现该错误 该错误显示在我尝试设置文件布局的 java 文件行上 这是 logcat 的完整转储 java lang RuntimeExceptio
  • 交互式变基后代码镜头无法正常工作

    在 VS2015 中 在我执行 git rebase i 并修改提交以更正作者姓名 我的一台机器中 git 配置中的拼写错误 后 通过 CodeLens 功能在代码中显示的关于作者和更改的所有来自 git 的代码元数据都消失了 在强制推送更
  • Zend Framework 1.9 和 Doctrine 集成

    我正在尝试设置 Zend Framework 和 Doctrine 之前有与 ZF 1 8 的讨论 将 Doctrine 与 Zend Framework 1 8 应用程序集成 该讨论没有考虑 AutoLoader Bootstrap 系统
  • ADB 服务器版本 (36) 与此客户端 (39) 不匹配;杀戮[重复]

    这个问题在这里已经有答案了 在测试设备上安装 Android O 预览版后 我的 ADB 停止工作并开始出现此错误 adb server version 36 doesn t match this client 39 killing adb
  • Matplotlib - 更改线条上方/下方的线条颜色

    I have a line plot and 2 hlines all using different colors and I m filling the areas where the main line crosses the hli
  • 根据长度将数据帧分割成相对均匀的块

    我必须创建一个函数 将提供的数据帧分割成所需大小的块 例如 如果数据帧包含 1111 行 我希望能够指定 400 行的块大小 并获得大小分别为 400 400 和 311 的三个较小的数据帧 是否有方便的函数来完成这项工作 存储和迭代切片数
  • C++ tokenize std string [重复]

    这个问题在这里已经有答案了 可能的重复 如何在 C 中标记字符串 您好 我想知道如何使用 strtok 标记 std 字符串 string line hello world bye char pch strtok line c str 我收
  • Symfony形式:自定义调用的setter

    我有一个实体的 Symfony 表单自定义类型 我想自定义提交表单时执行的代码 但仅限于字段 例如 Symfony 默认会这样调用 entity gt setFoo value 我想做这样的调用 entity gt doSomething
  • R 和面向对象编程

    在 R 中 以一种或另一种方式进行面向对象编程是非常可能的 但是 与 Python 等不同 有很多方法可以实现面向对象 The R oo包 S3和S4班 参考课 the 原型包 我的问题是 What majorR 中 OO 编程的这些方式有
  • 与发布后的实际下载大小相比,testflight 应用程序大小是否膨胀很大?

    我用 Unity 构建了一个 iOS 游戏 我将其上传到 App Store 启用了位码 IPA 约为 200 mb 在 iTunes Connect 上 它显示我的构建尺寸约为每个设备 30mb 我很高兴看到 但是当我将构建添加到 Tes
  • 如何在asp.net c#中将日期字符串“dd/MM/yyyy”格式转换为“MM/dd/yyyy”?

    我想在 C 中将字符串日期格式 dd MM yyyy 转换为 MM dd yyyy 例子 string d 25 02 2012 i want to convert into 02 25 2012 您可以将其解析为DateTime对象使用D
  • 方法签名中的 Final 关键字[重复]

    这个问题在这里已经有答案了 可能的重复 接口方法中的最终参数 有什么意义 在尝试尝试一些事情时 我遇到了其中描述的问题这一页 interface B public int something final int a abstract cla
  • 如何恢复之前显示的Fragment?

    我在我的项目中使用兼容性包 v4 但在保留Fragment从视图中删除后周围 我有我的Activity显示 2 个片段 左侧是菜单框架 右侧是内容窗格 菜单框架有 3 个可以显示的不同菜单 片段 这就是我替换菜单片段的方式 public v
  • R Shiny:如何将数据表添加到动态创建的选项卡

    我目前正在尝试创建动态创建的数据表 每个数据表都有自己的选项卡 选项卡的数量由用户确定 我已经使用了来自的代码这个帖子作为一个框架 我能够动态创建选项卡 但我不知道如何将数据表添加到选项卡 数据表也由用户输入确定 因此 例如 在 ui R
  • 具有验证功能的独特 CD-KEY 生成算法

    我正在尝试创建一个独特的 CD KEY 放入我们产品的包装盒中 就像用户用来注册产品的标准软件盒中的普通 CD KEY 一样 然而 我们不销售软件 我们销售的是用于犯罪和医疗目的的 DNA 采集套件 用户将通过邮件收到带有 CD KEY 的
  • Angular.js 中哪些“东西”可以注入到其他东西中?

    我很难理解 Angular 中的依赖注入 所以我的问题是 谁能解释一下我们可以将哪些 类型 如控制器 工厂 提供者等 注入到其他类型中 包括相同 类型 的其他实例 我真正要找的是这张表 上面写满了 y n 对于具有相同行 列的单元格 这意味