@Injectable()装饰器和提供者数组 [英] @Injectable() decorator and providers array

查看:188
本文介绍了@Injectable()装饰器和提供者数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Injectable()装饰器中以"root"身份提供的服务是否仍必须位于模块的providers数组中?

Does a service that is provided in "root" within the @Injectable() decorator still have to be in the providers array of the module?

Angular文档并没有真正给我答案,或者我不太清楚了解它.

The Angular documentation doesn't really give me an answer or I don't quite understand it.

在我的核心文件夹中,我有一个身份验证服务,该服务以root身份提供.为了使用所有提供的服务和组件,我不会将我的核心模块导入应用模块中.

Inside my core folder I have a authentication service which is provided in root. I wan't to import my core module inside the app module in order to use all the services and components provided.

我是否必须在模块的providers数组中另外设置服务,还是已经使用装饰器在根级别提供了足够的服务?

Do I have to additionally set up the service in the providers array of the module, or is it enough that it is already provided at root level using the decorator?

推荐答案

您提供的链接中的要点是注册服务的所有方法,从最不具体到最具体.

The bullet points in the link you provided are all different methods of registering services, from the least specific to most specific.

特定于应用程序-使用@Injectable({ providedIn: 'root' })

App-specific - use @Injectable({ providedIn: 'root' })

当您在根级别提供服务时,Angular会创建一个单个的HeroService共享实例,并将其注入到任何需要它的类中.在@Injectable()元数据中注册提供程序还允许Angular通过从未编译的应用程序中删除服务来优化应用程序.

When you provide the service at the root level, Angular creates a single, shared instance of HeroService and injects it into any class that asks for it. Registering the provider in the @Injectable() metadata also allows Angular to optimize an app by removing the service from the compiled app if it isn't used.

特定于模块-在模块提供者中注册

Module-specific - register in module providers

当您使用特定的NgModule注册提供程序时,该NgModule中的所有组件都可以使用服务的相同实例.要在此级别注册,请使用@NgModule()装饰器的providers属性,

When you register a provider with a specific NgModule, the same instance of a service is available to all components in that NgModule. To register at this level, use the providers property of the @NgModule() decorator,

特定于组件-在组件中注册

Component-specific - register in component

在组件级别注册提供程序时,将获得该组件的每个新实例的服务新实例.在组件级别,在@Component()元数据的providers属性中注册一个服务提供者.

When you register a provider at the component level, you get a new instance of the service with each new instance of that component. At the component level, register a service provider in the providers property of the @Component() metadata.

以上所有报价均来自官方服务和依赖项注入简介页面

All quotes above are from the official Introduction to services and dependency injection page

  • 如果只有一个模块,则前两种方法是等效的,只需要使用一种方法即可.使用@Injectable(默认的CLI方法)更容易.
  • 如果要在多个模块之间共享服务实例,请使用第一种方法.
  • 如果您希望每个独立模块一个实例,请使用第二种方法.
  • 如果您要与除一个组件外的所有组件共享一个应用程序级实例,那么对于一个异常组件,除了第三种方法外,还可以使用第一种方法.
  • If you only have one module, then the first two methods are equivalent and only need to use one method. It's easier to go with @Injectable - the default CLI approach.
  • If you want to share service instances between multiple modules, use the first method.
  • If you want one instance per independent module, use the second approach.
  • If you want to share an app-wide instance with all components except one, then use the first approach in addition to the third approach for the one anomalous component.

我认为大多数用例都属于前两种方法.

It is my opinion that most use cases would fall into the first two approaches.

提示:只需使用providedIn: 'root'.如果由于树状摇晃而未使用未使用的服务,则不会为该模块编译未使用的服务.声明特定于模块的服务似乎是多余的,并且正如我们将看到的那样,可能会引起问题.

Tip: just use providedIn: 'root'. Unused services won't be compiled for a module if it isn't used due to tree shaking. Declaring module-specific services seems redundant and, as we shall see, can cause problems.

注册模块特定服务有两种方法-从模块或从服务注册.

There are two ways to register module-specific services - either from the module or from the service.

模块

@NgModule({
  providers: [MyService]
})
export class MyModule {}

服务

@Injectable({ providedIn: MyModule })

后者是官方推荐的方法.声明providers数组是早期的宿醉.

The latter is the officially recommended approach. Declaring the providers array is a hangover from the earlier days.

来自文档:

以上示例显示了在模块中提供服务的首选方式.此方法是首选方法,因为如果没有注入,它将启用服务的树状摇动.如果无法在服务中指定应由哪个模块提供服务,则还可以在模块内声明服务的提供者

The example above shows the preferred way to provide a service in a module. This method is preferred because it enables tree-shaking of the service if nothing injects it. If it's not possible to specify in the service which module should provide it, you can also declare a provider for the service within the module

为什么您应该只使用providedIn: 'root'

因此,我们看到这种方法可摇树.到目前为止,一切都很好.但是,如果您仅尝试导入声明使用客户端的组件的模块,则最终将得到循环引用.

Why you should just use providedIn: 'root'

So we see that this approach is tree-shakeable. So far so good. But you will end up with circular references if you simply try to import the same module that the components consuming the clients are declared in.

进行此设置:

我的模块

declarations: [
  MyComponent
]

我的服务

@Injectable({ providedIn: MyModule })

我的组件

constructor(private myService: MyService) {}

  • my-service导入my-module
  • my-module导入my-component
  • my-component导入my-service
  • 存在循环依赖关系.

    此问题的解决方法是创建一个服务模块并将其导入到您的模块中.

    The workaround for this is to create a service module and import that into your module.

    我的模块

    imports: [
      MyModuleServices
    ],
    declarations: [
      MyComponent
    ]
    

    my-module-services

    my-module-services

    
    

    我的服务

    @Injectable({ providedIn: MyModuleServices })
    

    我的组件

    constructor(private myService: MyService) {}
    

    这是一个非常漫长的选择,而不是简单地使用providedIn: 'root'并让摇树来完成工作.

    This is a very long-winded alternative to simply using providedIn: 'root' and letting the tree shaking do the work.

    这篇关于@Injectable()装饰器和提供者数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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