本文,我们来了解下 Angular 的依赖注入 译者添加:维基百科中指出 -- 在软件工程中,依赖注入(Dependency Injection, DI)是指让一个物件接收它所依赖的其他物件。...推荐文章依赖注入是什么?如何使用它? 我们都知道在 Angular 中如何使用服务 services 的标准方法。将服务标记为可注入并将其放入模块中的 provider 部分中。...如下: 对于依赖注入,我们有很多的小技巧可以使用。比如,在模块中Angular 可以转换一行 TestService 为不同行写法。...我们放在 provider 部分的每个服务,都会转换为带有两个属性的对象。在 provide 属性中,我们可以使用类名或者我们可以创建一个独一无二的键并注入一个对象。我们甚至可以注入一个变量。...现在,希望你了解了 Angular 依赖注入的魅力。 如果你想详解更多的相关代码内容,请戳 这里。 本文为译文,采用意译的形式。
生成的JavaScript里没有对应的语句: ? 换一个方式:在shipping Component里导入,然后通过构造函数参数的方式注入: ? 最后生成的JavaScript代码: ?...可见无论TypeScript里导入的是http client还是http client module,这些TypeScript里的变量名都不重要,最后转换成的JavaScript代码里,这两个变量是完全等价的
首先介绍 Angular 中依赖注入的相关概念: Service 服务 Service 的表现形式是一个class,可以用来在组件中复用 比如 Http 请求获取数据,日志处理,验证用户输入等都写成Service...import { Injectable } from '@angular/core'; // 在 Angular 中,要把一个类定义为服务,就要用 `@Injectable` 装饰器来提供元数据 @Injectable...一般不用自己手动注入,Angular 会在启动过程中为你创建全应用级注入器以及所需的其它注入器。..., // providers 告诉 Angular 应用哪些对象需要依赖注入 // providers 是个数组,每一项都是provider providers: [ // 简写,...其他组件不可以注入。 当声明在组件和模块中的提供器具有相同的token时,声明在组件中的提供器会覆盖模块中的那个提供器。
一、依赖注入基础 1.1 依赖注入的概念 依赖注入的基本思想是:将组件所依赖的服务提供者注入进来,而不是在组件内部直接创建。...1.2 依赖注入的优势 使用依赖注入的好处有: 降低组件之间的耦合度,提高可维护性。 使组件可重用和更易于测试。 能将不同的实现切换进来,提高程序灵活性。 统一管理依赖模块。...二、Angular中的依赖注入 Angular有自己的依赖注入框架,可以自动解析组件的依赖关系,避免了直接在组件中使用new一个服务的紧耦合方式。...2.1 @Injectable装饰器 @Injectable装饰器用于标记一个类为可注入的,可以被注入器实例化。...class CustomInjector extends Injector { constructor(@Inject(ENV_TOKEN) private env: string) { // 注入环境标记
依赖注入的概念 在软件工程中,依赖注入是种实现控制反转用于解决依赖性设计模式。一个依赖关系指的是可被利用的一种对象(即服务提供端) 。依赖注入是将所依赖的传递给将使用的从属对象(即客户端)。...Angular 利用依赖注入机制改变了这一点,在该机制下,如果服务 A 中需要服务 B,即服务 A 依赖于服务 B,那么我们期望服务 B 能被自动注入到服务 A 中,如下图所示: ?...在 Angular 中,依赖注入包括以下三个部分: 提供者负责把一个令牌(可能是字符串也可能是类)映射到一个依赖的列表。它告诉 Angular 该如何根据指定的令牌创建对象。...在 Angular 中我们通过 Provider 来描述与 Token 相关联的依赖对象的创建方式。...在 Angular 中依赖对象的创建方式分为以下四种: useClass useValue useExisting useFactory Provider 的分类 在 Angular 中 Provider
Angular官方文档 Specifying a provider token If you specify the service class as the provider token, the...如果将一个服务类直接指定成provider token,默认的行为就是,injector直接用new来初始化那个类。 上面的例子,会触发Logger的构造函数。...等价于: [{ provide: Logger, useClass: Logger }] 这个完整的声明在Angular官方文档里称为expanded provider configuration..., 是一个包含两个属性的对象。...下列的配置,会导致Component需要使用OldLogger时,会返回NewLogger的singleton实例。当然,如果请求NewLogger,亦会返回NewLogger实例。
上下文:我实现了一个hero service,在其构造函数里添加了一些打印语句: 在另一个Component的构造函数里将其注入: 运行时,观察service构造函数如何被调用的: function getNodeInjectable
类的实例字段定义必须在实例方法之前: image.png 尽量避免用String类型: image.png image.png 我在自己Component的构造函数里试图注入一个service...image.png 这是我的service类,已经用 @Injectable()进行了标注,说明它可以被注入到其他Component里去: image.png 解决方案:在需要使用这个service...类的module里,在providers区域进行声明: image.png 之后注入成功: image.png
官方文档 Angular 中有两个注入器层次结构: (1) ModuleInjector 层次结构 —— 使用 @NgModule() 或 @Injectable() 注解在此层次结构中配置 ModuleInjector...层次结构中的下一个父注入器是 NullInjector(),它是树的顶部。...这些请求将继续转发,直到 Angular 找到可以处理该请求的注入器或用完祖先 ElementInjector。...例如,如果提供者已经在需要此服务的组件中本地注册了,则 Angular 不会再寻找同一服务的其它提供者。...@Optional() @Optional() 允许 Angular 将你注入的服务视为可选服务。这样,如果无法在运行时解析它,Angular 只会将服务解析为 null,而不会抛出错误。
在 Angular 中定义一个服务很简单,主要在类之前加上 @Injectable 装饰器的功能。这是最常见的依赖注入方式 useClass,其他具体参见这里。...bootstrap: [...] }) export class AppModule { } 使用的时候需要在构造器中建立关联: import { Component } from '@angular...,所以该模块中的所有组件使用这个服务时,使用的都是同一个实例。...这个可以从Service中的数据变化来看出。 Angular还有个分层依赖注入的概念,也就是说,你可以为任一组件创建自己独立的服务。...就像上面的例子,如果想要HomeComponent不和它的父组件同使用一个服务实例的话,只要在该组件中重新注入即可: ...
文章目录 前言 块级元素 行内元素 行内块级元素 ---- 前言 HTML中的标记 块级元素 h1-h6>>1-6级标题 p>>段落 div>>定义文档中的节 ul>>定义无序列表 ol>>定义有序列表...>定义定义列表中项目的描述 menu>>定义命令的菜单/列表 table>>定义表格 caption>>定义表格标题 tbody>>定义表格主体 thead>>定义表格头部 tfoot>>定义表格中的表注内容...(脚注) tr>>定义表格中的行 th>>定义表格中的表头单元格 colgroup>>定义表格中供格式化的列组 col>>定义表格中一个或多个列的属性值。...比如章节、页眉、页脚或文档中的其他部分 article>>定义文章 aside>>定义页面内容之外的内容。【可用作文章的侧栏。】 datails>>定义元素的细节。...) iframe>>定义内联框架 canvas>>定义图形 td>>定义表格中的单元格
MyNewService的初始化过程: ? InjectionToken: ? this.records: 一个巨大的map,key为injection token, ?...value的数据结构如下图所示: ? useClass的实例化,在代码17207的record.factory方法调用里进行: ? ?
假设我在app.config.ts里定义了一个interface AppConfig和一个对象HERO_DI_CONFIG, 我想将后者注入到一个类的构造函数里去: export interface AppConfig...{ apiEndpoint: string; title: string; } import { InjectionToken } from '@angular/core';...是injection token的描述信息。...在NgModule里使用useValue注入: ? 在需要使用这个依赖的地方,将token APP_CONFIG传入@Inject: ? 最后的效果: ?...要获取更多Jerry的原创文章,请关注公众号"汪子熙": ?
例子: import { Injectable } from '@angular/core'; let count = 0; @Injectable() export class MyService...Service构造函数的断点只触发了一次: ? ? 这个单例行为在Angular DI帮助文档里有提到: https://angular.io/guide/glossary#injector ? ?...什么时候会失去单例的特性呢?...表面上看,请求MyService时,也使用MyNewService进行类的实例化,似乎我们会得到MyNewService的单例。...用了useExisting之后的效果: ?
provider使用一个DI token配置injector,后者使用该token创建一个具体的能用于运行时的实例,该实例可以注入到Component,指令,管道和其他服务里。...useValue"'], log: silentLoggerFn }; 使用useValue返回这个对象: [{ provide: Logger, useValue: SilentLogger }] 如何只注入一个简单的字符串呢...TypeScript里的接口是一个design time的概念,而DI框架需要一个运行时载体即DI token,因此接口并不能直接参与到Angular的DI中去。...解决方案1 在NgModule里提供和注入configuration对象: providers: [ UserService, { provide: APP_CONFIG, useValue:...HERO_DI_CONFIG } ], 解决方案2 使用InjectionToken object. import { InjectionToken } from '@angular/core'; export
Angular 将为我们的每个模块(module)生成一个注入器 Injector,因此在我们的例子中,它将采用 AppModule(我们的装饰类)并创建一个名为 AppModuleInjector 的注入器...我们会从上述生成代码中学习三个知识点:类的属性、模块导入以及依赖注入机制的工作方式。...这是为了避免在不需要时创建提供程序的实例,同时提高初始渲染性能。 每当我们谈到 Angular 中的注入器时,它指的是从我们的模块中生成(编译)的代码。...当 Angular 查找依赖项(例如我们通过构造函数注入的依赖项)时,它会在模块注入器中查找,如果找不到则向上遍历父模块。 如果它不存在,将会抛出一个错误。...当我们在构造函数中使用类型定义时,Angular 使用这些类型(即类)作为查找依赖项的标记。 然后将该令牌传递给 getInternal 并返回依赖项的实例(如果存在)。
classRef); } } } return factory; } UseValue和UseExisting可以在此处打断点调试: 而useClass的分支在下图...,由此可见,useClass就是简单的new操作: factory其实就是构造函数,只是由于Chrome开发者工具的限制,无法正确显示出来: 这里可见,useExisting如果没有实例,还是会调用构造函数...new一个新的出来。
问题点在哪里 先做一个小声明,我们现在拥有一个AppComponent,并使用DI系统向其中注入了一个NameService,因为我们使用的是Typescript,所以需要做的工作就是在构造函数的参数中声明变量..."; } } 上述代码是可以正常工作的,如果我们将nameService.ts中的代码直接嵌入app.ts时,会产生哪些变化呢?...无论如何,当我们在调试器中打开Pause on caught exceptions功能时,就会在Angular框架中捕获这个错误: Cannot resolve all parameters for...小结 这个场景并不会经常出现,一般它只在当我们想要注入在同一个文件中声明的类时才会发生,大多数情况下我们在一个文件中只会声明一个类,并且会在文件的头部引入其他依赖的类,以此来保证不会被class不进行变量提升的特性造成困扰...但有时候循环引用可能无法避免,当类A引用类B,同时B又引用A时,就会陷入困境:它们中的某一个必须先定义。 forwardRef( )建立一个间接引用,供Angular随后解析。
我们调用InjectionToken构造器,创建一个新的InjectionToken实例时,除了传入一个字符串作为description,还可以指定一个options结构: const MY_SERVICE_TOKEN...console.log('MyService factory called'); return new MyService(); } }); 该options里可以指定一个factory函数,在里面实现条件式的被依赖实例注入逻辑
这个例子的完整源代码: import { Component, OnInit, Injectable, Injector } from '@angular/core'; @Injectable() class...implements OnInit { constructor() { } ngOnInit(): void { } } 单步调试 Injector.create 由实现源代码可见,Angular...NeedsService 的依赖服务是 UsefulService,维护在 deps 数组里: ? 观察最后返回的 injector 实例里,到底包含了哪些数据: ?
领取专属 10元无门槛券
手把手带您无忧上云