【问题标题】:Importing Injectables and Angular Services导入 Injectables 和 Angular 服务
【发布时间】:2020-09-10 16:41:29
【问题描述】:

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

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

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

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

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

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

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

对

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

【问题讨论】:

    标签: angular angular-services injectable


    【解决方案1】:

    打算再深入一点地回答...

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

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

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

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

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

    【讨论】:

    • 我忘了提到我打算将 addToList() 声明为静态方法。为什么在服务中使用静态方法是一个坏主意/坏习惯?
    • 这违反了依赖注入的原则。静态方法不能保持或使用状态或使用依赖项,那么为什么它甚至在服务上呢?如果您有一个静态方法,它可能并不真正属于该服务,而应该只是其他地方的实用功能。如果您在某些地方使用服务实例而在其他地方使用静态方法,您的应用程序会变得混乱。
    • 非常感谢您的澄清 :)
    【解决方案2】:

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

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

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

    【讨论】:

    • 您在第 1 点上搞错了。@Injectable() 确实将其注册为要注入服务的内容。只要提供了未标记@Injectable() 的东西,您就可以安全地注入它们。第 3 点并不完全正确,除非您希望它们成为,否则服务在角度上特别不是单例,您可以在模块或根级别提供,并且仍然在组件中提供以获得不同的实例。这里没有对错,这取决于服务的目的。
    • @bryan60 我的第一点是从文档中 1:1 复制的 :),但是您在回答中已经解释了第 1 点真的很棒!
    • 文档对此有点不清楚,但请自行查看:stackblitz.com/edit/angular-ivy-trxua5
    【解决方案3】:
    @Injectable({
      providedIn: 'root',
    })
    

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

    dummy= new DummyService()
    

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

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

    • 依赖注入的目标是简化测试并使代码可重用。

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      • 2020-08-01
      • 2014-09-19
      • 2017-08-24
      • 2018-08-25
      相关资源
      最近更新 更多