为什么我可以在不导入其提供程序模块的情况下使用服务?
Why can I use a service without importing its provider module?
我正在努力研究 angular 应用程序中的多个 NgModule 如何协同工作,尤其是我正在尝试了解如何正确地将提供常用服务的 SharedModule
导入到 lazily已加载功能模块。
一步一步:
- 我创建了一个新的 angular 应用程序:
ng new playground --routing
- 我创建了一个
SharedModule
来提供服务和常用的声明:ng generate module shared
- 我在共享模块中创建了一个服务:
ng generate service shared/foo
现在我的 SharedModule
目录中有一个 FooService
,但我希望 SharedModule
提供该服务。因此,我将 @Injectable
注释更改为:
@Injectable({
providedIn: SharedModule
})
因为我想保持我的 AppModule
和它的服务注入器尽可能干净(在现实世界中以后,我也会使用 CoreModule
但那不是我的问题的范围让我们回到正轨)
- 现在,我想添加一个新功能,所以我生成了一个我想延迟加载的新 FeatureModule:
ng generate module feature --routing
- 现在,我有一个
FeatureModule
让我们通过添加路由到 AppRoutingModule
:
来延迟加载功能模块
const routes: Routes = [
{
path: 'feature',
loadChildren: './feature/feature.module#FeatureModule'
}
];
我假设在 AppModule
模板的某处,我有一个 <router-outlet>
和一个导航到 /feature
的 routerLink
。
- 在
FeatureModule
中,我们还需要生成一个我们想要在导航时显示的组件:ng generate component feature/start
为了使我的新 StartComponent
成为路由到我的 FeatureModule
时显示的初始组件,我将调整 FeatureRoutingModule
中的路由:
const routes: Routes = [{
path: '',
component: StartComponent
}];
现在,我想在 StartComponent
中使用我添加到 SharedModule
的 FooService
。所以我把它注入那里。
export class StartComponent implements OnInit {
constructor(private foo: FooService) { }
ngOnInit() {
}
}
ng serve
- 导航到
FeatureModule
并看到运行时错误!这是我所期望的,因为我没有在FeatureModule
中导入SharedModule
,所以注入器不知道FooService
。
- 到目前为止一切顺利,现在让我们进入我的问题的要点:
- 我将再创建一个未延迟加载的模块,即
CoreModule
。为了保持 AppModule
尽可能干净和尽可能小,我将在 CoreModule
中实现初始应用程序。 ng generate module core
- 当然我们还需要
CoreModule
中的一些组件:ng generate component core/core-main
现在,我也想在我的新 CoreMainComponent
中使用 FooService
。所以,我们也把它注入到那里:
export class CoreMainComponent implements OnInit {
constructor(private foo: FooService) { }
ngOnInit() {
}
}
这次我不会忘记在我的CoreModule
中导入SharedModule
。但是记得我还是忘记了,没有在FeatureModule
中导入SharedModule
。当然,我必须在某处使用 CoreMainComponent
,所以我将其导出。所以这是新的 CoreModule
装饰:
@NgModule({
imports: [
CommonModule,
SharedModule
],
declarations: [CoreMainComponent],
exports: [CoreMainComponent]
})
export class CoreModule { }
同时将 CoreModule
导入 AppModule
并在 AppModule 的模板中添加一个 <app-core-main></app-core-main>
。
ng serve
- 我的期望:一旦我单击 link 延迟加载并导航到我的
FeatureModule
,我仍然会遇到运行时错误。 CoreModule
导入 SharedModule
,但 FeatureModule
不导入。但是在这两个模块中,都使用了 FooService
。
- 事实上,它有效。我可以毫无错误地使用功能模块中的组件。所以注入器似乎知道
FooService
即使在 FeatureModule
中,尽管我没有在那里导入它。我本以为它会失败
- 谁能帮我理解为什么会这样?
这就是它应该如何工作的,每当你在你的AppModule
中导入任何非延迟加载模块然后那个[=21=的服务]非延迟加载模块在整个应用程序中可用。
除此之外的原因,在Angular父子模块中,共享同一个Injector!。但是在 FeatureModule
( 延迟加载模块 )的情况下,它们有自己的注入器,因此延迟加载模块中提供的任何服务仅可用于该模块。
在你的情况下,你可以说 CoreModule
是 AppModule
的子模块,而 SharedModule
是 CoreModule
的子模块,因为两者都是 non - 延迟加载模块 这就是为什么你的 FooService
在 FeatureModule
中自动可用的原因。
我正在努力研究 angular 应用程序中的多个 NgModule 如何协同工作,尤其是我正在尝试了解如何正确地将提供常用服务的 SharedModule
导入到 lazily已加载功能模块。
一步一步:
- 我创建了一个新的 angular 应用程序:
ng new playground --routing
- 我创建了一个
SharedModule
来提供服务和常用的声明:ng generate module shared
- 我在共享模块中创建了一个服务:
ng generate service shared/foo
现在我的
SharedModule
目录中有一个FooService
,但我希望SharedModule
提供该服务。因此,我将@Injectable
注释更改为:@Injectable({ providedIn: SharedModule })
因为我想保持我的
AppModule
和它的服务注入器尽可能干净(在现实世界中以后,我也会使用CoreModule
但那不是我的问题的范围让我们回到正轨)- 现在,我想添加一个新功能,所以我生成了一个我想延迟加载的新 FeatureModule:
ng generate module feature --routing
- 现在,我有一个
FeatureModule
让我们通过添加路由到
来延迟加载功能模块AppRoutingModule
:const routes: Routes = [ { path: 'feature', loadChildren: './feature/feature.module#FeatureModule' } ];
我假设在
AppModule
模板的某处,我有一个<router-outlet>
和一个导航到/feature
的routerLink
。- 在
FeatureModule
中,我们还需要生成一个我们想要在导航时显示的组件:ng generate component feature/start
为了使我的新
StartComponent
成为路由到我的FeatureModule
时显示的初始组件,我将调整FeatureRoutingModule
中的路由:const routes: Routes = [{ path: '', component: StartComponent }];
现在,我想在
StartComponent
中使用我添加到SharedModule
的FooService
。所以我把它注入那里。export class StartComponent implements OnInit { constructor(private foo: FooService) { } ngOnInit() { } }
ng serve
- 导航到
FeatureModule
并看到运行时错误!这是我所期望的,因为我没有在FeatureModule
中导入SharedModule
,所以注入器不知道FooService
。 - 到目前为止一切顺利,现在让我们进入我的问题的要点:
- 我将再创建一个未延迟加载的模块,即
CoreModule
。为了保持AppModule
尽可能干净和尽可能小,我将在CoreModule
中实现初始应用程序。ng generate module core
- 当然我们还需要
CoreModule
中的一些组件:ng generate component core/core-main
现在,我也想在我的新
CoreMainComponent
中使用FooService
。所以,我们也把它注入到那里:export class CoreMainComponent implements OnInit { constructor(private foo: FooService) { } ngOnInit() { } }
这次我不会忘记在我的
CoreModule
中导入SharedModule
。但是记得我还是忘记了,没有在FeatureModule
中导入SharedModule
。当然,我必须在某处使用CoreMainComponent
,所以我将其导出。所以这是新的CoreModule
装饰:@NgModule({ imports: [ CommonModule, SharedModule ], declarations: [CoreMainComponent], exports: [CoreMainComponent] }) export class CoreModule { }
同时将
CoreModule
导入AppModule
并在 AppModule 的模板中添加一个<app-core-main></app-core-main>
。ng serve
- 我的期望:一旦我单击 link 延迟加载并导航到我的
FeatureModule
,我仍然会遇到运行时错误。CoreModule
导入SharedModule
,但FeatureModule
不导入。但是在这两个模块中,都使用了FooService
。 - 事实上,它有效。我可以毫无错误地使用功能模块中的组件。所以注入器似乎知道
FooService
即使在FeatureModule
中,尽管我没有在那里导入它。我本以为它会失败 - 谁能帮我理解为什么会这样?
这就是它应该如何工作的,每当你在你的AppModule
中导入任何非延迟加载模块然后那个[=21=的服务]非延迟加载模块在整个应用程序中可用。
除此之外的原因,在Angular父子模块中,共享同一个Injector!。但是在 FeatureModule
( 延迟加载模块 )的情况下,它们有自己的注入器,因此延迟加载模块中提供的任何服务仅可用于该模块。
在你的情况下,你可以说 CoreModule
是 AppModule
的子模块,而 SharedModule
是 CoreModule
的子模块,因为两者都是 non - 延迟加载模块 这就是为什么你的 FooService
在 FeatureModule
中自动可用的原因。