我正在学习Angular中的Injectables和Services,我不清楚关于Injectable的某些导入和默认特性。具体来说,Angular中的服务应该在什么时候:
-
有@Injectables标签吗?我看到过一篇没有使用它的博客文章。当你去掉它时会发生什么?去掉这个标签会如何改变服务的行为方式?
-
是否在app.module的providers数组中声明?
-
是否在单个组件的提供程序数组中声明,而不是在app.module中声明?
-
当使用@Injectables标记时,providedIn关键字的默认值是什么?如果您的服务中没有定义这个关键字,那么应该对关键字的值和服务的范围进行什么假设?
-
假设我有一个具有以下特征的服务(我们称之为
DummyService
):具有@Injectables标记,不定义providedIn,不在任何提供者数组中声明(既不是app.module,也不是任何单个组件)。- 5.a)由于没有指定providedIn,并且该服务没有在任何提供程序数组中声明,因此该服务可以与同级组件共享吗
- 5.b)当从导入DummyService的组件调用DummyServices时,与这些用例有什么区别:
DummyService.addToList("Stacy");
与
constructor(private _dummyservice: DummyService){}
ngOnInit(){
this.dummyservice.addToList("Stacy");
}
将更深入地回答。。。
-
@Injectable
装饰器向注入器注册服务。将服务标记为可注入意味着可以将其他服务注入该服务。如果您省略它,您可以安全地提供和注入服务,但如果您试图注入服务,angular将向您抛出错误。不过,通常情况下,最佳做法是将所有服务标记为@Injectable()
,无论您是否向它们注入。 -
目前使用
providedIn: 'root'
是注册单例服务的首选方式,或者您只想在应用程序范围内拥有一个共享实例的服务,这或多或少相当于将其添加到app.module中的providers数组中。但是,如果您需要使用像工厂提供程序这样的特殊提供程序,则需要使用app.moduleproviders数组。providedIn: 'root'
对于延迟加载模块也很有用,因为angular的早期迭代在延迟加载模块中遇到了一些问题,因为它们自己的提供程序阵列获得了不同的服务副本,这些副本意味着是单体。CCD_ 6选项很好地解决了这个问题。 -
在组件中提供意味着该组件将获得给定服务的自己的实例,并且该组件的所有子级都将接收给定服务的该实例。如果您仅在app.module(或root)级别提供,那么所有组件都将在应用程序范围内接收相同的服务。如果合适的话,您可以在根AND组件级别提供,但您应该知道它的作用(常见的情况是某种全局与本地警报服务)。
-
";默认";提供什么都没有。如果省略它,则必须在提供者数组中适当地声明服务才能注入和使用它。在将其声明为根提供的服务或将其放入提供者数组之前,它没有作用域。
-
如果不提供该服务,则无法注入,完全停止。问题5a和5b都是不相关的,因为不能注入服务。您的示例似乎是以静态方式访问服务方法,这通常是个坏主意。重要的是实际注入您打算使用的服务,以使依赖项注入对您的应用程序有用。
1.)@Injectable
装饰器,它将类标记为可提供并作为依赖项注入。(发件人:https://angular.io/api/core/Injectable)
表示此类可以与Injector一起使用。但是Angular实际上不能在任何地方注入它,除非您使用该服务的提供者配置Angular依赖项注入器。这可以在@Injectable
、@NgModule()
或@Component()
内部完成
2.)在app.module
的providers数组中声明服务与@Injectable({providedIn: 'root'})
相同。你不需要两者都做。使用providedIn
是目前推荐的新方法
3.)Angular中的服务可以是singleton,因此如果您在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
,则必须通过提供者阵列设置服务。
5.)Angular DI无法重新提供您的服务。请参见此处:https://stackblitz.com/edit/angular-ivy-c48sfa?file=src/app/app.module.ts
@Injectable({
providedIn: 'root',
})
上面的代码告诉angular,获取这个类并将其加载到注入器/容器中,该注入器或容器可以被认为是组件顶部的容器。Angular将自动为我们创建每个服务的单个实例。我们不像那样创建自己
dummy= new DummyService()
angular将为我们提供它,并使其可用于注射器容器内的所有不同组件。这将使代码可重用。
因此,每当有人在任何组件中调用DummyService
时,angular都会发送DummyService的实例。您可以在组件类的构造函数中手动创建它。
- 依赖注入的目标是使测试更容易,并使代码可重用
如果你去浏览器并检查编译器,到达定义类的那一行,你会看到这样的东西:
AppComponent.ctorParameters=() ⇒ {type:_dummy_service__WEBPACK_IMPORTED_MODULE_2__[“DummyService” ]} ]
typescript文件中的所有代码都在浏览器中执行之前由typescript编译器进行处理。然后webpack接管了所有的类型,所有的注释,所有的公共和私有的东西都被撕掉了。因为你的浏览器不知道如何理解打字。类组件构造函数参数也像上面一样作为一个新属性被删除。