0

我正在学习 Angular 中的 Injectables 和 Services,但我不清楚有关注射器的某些导入和默认特性。具体来说,什么时候应该在 Angular 中提供服务:

  1. 有@Injectables 标签吗?我看过一篇没有使用它的博文。当您将其忽略时会发生什么?忽略此标记将如何改变服务的行为方式?

  2. 在 app.module 的 providers 数组中声明?

  3. 在单个组件的 providers 数组中声明,而不是在 app.module 中声明?

  4. 使用 @Injectables 标签时,providedIn 关键字的默认值是多少?如果您的服务中未定义此关键字,那么应该假设关键字的值和服务的范围是什么?

  5. 假设我有一个具有这些特征的服务(我们称之为DummyService):具有@Injectables 标记,未定义提供的输入,未在任何提供程序数组中声明(既不是 app.module 也不是任何单个组件)。

    • 5.a) 由于providedIn 未指定且服务未在任何providers 数组中声明,该服务是否可以与兄弟组件共享?
    • 5.b) 从导入 DummyService 的组件调用 DummyService 时,与这些用例有什么区别:
DummyService.addToList("Stacy");

对比

constructor(private _dummyservice: DummyService){} 
ngOnInit(){
 this.dummyservice.addToList("Stacy");
}
4

3 回答 3

1

会回答得更深入一点...

  1. @Injectable装饰器向注入器注册您的服务。将服务标记为可注入意味着可以将其他服务注入到该服务中。如果你省略它,你可以安全地提供和注入服务,但是如果你尝试注入它,angular 会向你抛出一个错误。不过,一般来说,最佳实践是将所有服务标记为@Injectable(),无论您是否注入它们。

  2. 当前使用providedIn: 'root'的是注册单例服务的首选方式,或者您只想拥有一个共享应用程序实例的服务,它或多或少等同于将其添加到 app.module 中的 providers 数组中。但是,您想要使用 app.module 提供程序数组的情况是您需要使用像工厂提供程序这样的特殊提供程序。providedIn: 'root'对于延迟加载的模块也很有用,因为早期的 Angular 迭代在延迟加载的模块中存在一些问题,它们自己的提供程序数组获取不同的服务副本,这些副本意味着单例。该providedIn选项很好地解决了这个问题。

  3. 在组件中提供意味着该组件将获得给定服务的自己的实例,并且该组件的所有子代都将收到给定服务的该实例。如果您仅在 app.module(或根)级别提供,那么所有组件将在应用程序范围内接收相同的服务。如果合适,您可以在根和组件级别提供,但您应该知道这是做什么的(这种情况的常见情况是某种全局与本地警报服务)。

  4. providedIn 的“默认”是什么。如果省略它,则必须在提供程序数组中适当地声明服务以注入和使用它。在您将其声明为 root 提供或将其放入 providers 数组之前,它没有作用域。

  5. 不提供服务是无法注入的,句号。问题 5a 和 5b 都无关紧要,因为无法注入服务。您的示例似乎以静态方式访问服务方法,这通常是一个坏主意。实际注入您打算使用的服务以使依赖注入对您的应用程序有用,这一点很重要。

于 2020-09-10T17:35:15.267 回答
1

1.) @Injectable将类标记为可提供并作为依赖项注入的装饰器。(来自:https ://angular.io/api/core/Injectable )

意味着此类可以与 Injector 一起使用。但是 Angular 实际上无法在任何地方注入它,除非您使用该服务的提供者配置 Angular 依赖注入器。这可以在内部完成@Injectable@NgModule()或者@Component()

2.) 在 providers 数组中声明服务app.module@Injectable({providedIn: 'root'}). 你不需要两者都做。使用providedIn是新的/当前推荐的方式。

3.) Angular 中的服务可以是单例的,因此如果您在 中提供服务app.module,您可以在任何地方访问该服务,并且它始终是同一个实例。如果您在组件级别提供服务,则每个组件实例都会获得自己的服务实例。

@Component({providers: [DummyService], ...})
export class FooComponent {
  constructor(
    private readonly _dummyService: DummyService,
  ) {}
}

本质上是一样的

@Component(...)
export class FooComponent {
  private readonly _dummyService = new DummyService();
  constructor() {}
}

除了后者不使用 Angular 的 DI。

4.) {providedIn: 'root'},如果providedIn未设置,则必须通过 providers-array 设置服务。

5.) Angular DI 无法解决您的服务。见这里:https ://stackblitz.com/edit/angular-ivy-c48sfa?file=src/app/app.module.ts

于 2020-09-10T17:00:58.613 回答
0
@Injectable({
  providedIn: 'root',
})

上面的代码告诉 Angular,获取这个类并将其加载到注入器/容器中,该注入器/容器可以被认为是组件顶部的容器。Angular 会自动为我们创建每个服务的单个实例。我们不创造自己喜欢

dummy= new DummyService()

angular 将为我们提供它,并使其可用于注入器容器内的所有不同组件。这将使代码可重用。

因此,每当有人调用DummyService任何组件时,Angular 都会发送 DummyService 的实例。您可以在组件类的构造函数中手动创建它。

  • 依赖注入的目标是使测试更容易并使代码可重用。

如果你进入浏览器并检查编译器,进入定义你的类的那一行,你会看到如下内容:

AppComponent.ctorParameters=() ⇒  {type:_dummy_service__WEBPACK_IMPORTED_MODULE_2__[“DummyService” ]} ]

打字稿文件中的所有代码甚至在浏览器中执行之前都已由打字稿编译器处理。然后 webpack 接管,所有这些类型,所有这些注释,所有公共和私有的东西都被撕掉了。由于您的浏览器不知道如何理解打字稿。类组件的构造函数参数也像上面一样作为新属性被删除。

于 2020-09-11T22:30:02.800 回答