如何在惰性加载模块中提供服务并将该服务的范围限定为惰性加载模块及其组件?
How do I provide a service in a lazy-loaded module and have that service scoped to just the lazy-loaded module and its components?
在 angular 文档常见问题解答部分,它指出,"Unlike providers of the modules loaded at launch, providers of lazy-loaded modules are module-scoped." link
这里的'module-scoped'是仅仅指模块还是扩展到包括属于该模块的所有组件?
我问的原因是因为我有一个延迟加载的模块,其中包含 2 个组件。我在模块中注册了一项服务,但出于某种原因,每个组件都获得了该服务的不同实例。
我需要更改什么才能在我的延迟加载模块中提供 LazyModuleService 并将该服务的范围限定为延迟加载模块及其组件?请包括所需的任何其他文件。我试图做一个通用的例子来帮助其他可能发现这个问题的人。
懒加载模块:
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
import { LazyModuleService } from './lazy-module.service';
@NgModule({
imports: [
CommonModule,
],
declarations: [
Component1,
Component2,
],
})
export class LazyLoadedModule { }
只需将您的 LazyModuleService 添加为您的 LazyLoadedModule 中的提供者。您将只能在该模块的组件中使用它。
延迟加载的工作原理:
经过深入调查,问题似乎与延迟加载的实现方式有关。
在你的例子中,你的延迟加载模块实际上有路由到其中的 2 个不同的组件——这两个组件都直接公开为 Router.forChild 路由。但是,结果,当您导航到每个组件时,您的延迟加载模块的提供程序的一个单独实例被添加到每个组件。
由于您实际上希望延迟加载模块中的所有组件共享它们所提供服务的同一个实例,因此您需要创建一个 'root' 组件,然后让您的两个组件成为该组件的子组件根组件。
似乎在延迟加载时,模块中的提供程序将被添加到模块根部组件的注入器中。由于您有两个 'root components',它们每个都有单独的服务实例。
解决方案是创建一个根组件,其注入器将接收延迟加载的服务,然后可以由任何子组件共享。
Angular 6 提供了出色的内置解决方案。
如果您使用的是 Angular 6+(检查您的 package.json 以了解),您可以以不同的方式提供应用程序范围的服务。
您可以在 @Injectable() 中设置以下配置,而不是将服务 class 添加到 AppModule 中的 providers[] 数组:
@Injectable({providedIn: 'root'})
export class MyService { ... }
这与:
完全相同
export class MyService { ... }
和
import { MyService } from './path/to/my.service';
@NgModule({
...
providers: [MyService]
})
export class MyService { ... }
使用这种新语法是完全可选的,传统语法(使用 providers[] )仍然有效。 "new syntax" 确实提供了一个优势:服务可以通过 Angular 延迟加载(在幕后)并且可以自动删除冗余代码。这可以带来更好的性能和加载速度 - 尽管这通常只适用于更大的服务和应用程序。
来源:Udemy
在 angular 文档常见问题解答部分,它指出,"Unlike providers of the modules loaded at launch, providers of lazy-loaded modules are module-scoped." link
这里的'module-scoped'是仅仅指模块还是扩展到包括属于该模块的所有组件?
我问的原因是因为我有一个延迟加载的模块,其中包含 2 个组件。我在模块中注册了一项服务,但出于某种原因,每个组件都获得了该服务的不同实例。
我需要更改什么才能在我的延迟加载模块中提供 LazyModuleService 并将该服务的范围限定为延迟加载模块及其组件?请包括所需的任何其他文件。我试图做一个通用的例子来帮助其他可能发现这个问题的人。
懒加载模块:
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { Component1 } from './component1.component';
import { Component2 } from './component2.component';
import { LazyModuleService } from './lazy-module.service';
@NgModule({
imports: [
CommonModule,
],
declarations: [
Component1,
Component2,
],
})
export class LazyLoadedModule { }
只需将您的 LazyModuleService 添加为您的 LazyLoadedModule 中的提供者。您将只能在该模块的组件中使用它。
延迟加载的工作原理:
经过深入调查,问题似乎与延迟加载的实现方式有关。
在你的例子中,你的延迟加载模块实际上有路由到其中的 2 个不同的组件——这两个组件都直接公开为 Router.forChild 路由。但是,结果,当您导航到每个组件时,您的延迟加载模块的提供程序的一个单独实例被添加到每个组件。
由于您实际上希望延迟加载模块中的所有组件共享它们所提供服务的同一个实例,因此您需要创建一个 'root' 组件,然后让您的两个组件成为该组件的子组件根组件。
似乎在延迟加载时,模块中的提供程序将被添加到模块根部组件的注入器中。由于您有两个 'root components',它们每个都有单独的服务实例。
解决方案是创建一个根组件,其注入器将接收延迟加载的服务,然后可以由任何子组件共享。
Angular 6 提供了出色的内置解决方案。 如果您使用的是 Angular 6+(检查您的 package.json 以了解),您可以以不同的方式提供应用程序范围的服务。
您可以在 @Injectable() 中设置以下配置,而不是将服务 class 添加到 AppModule 中的 providers[] 数组:
@Injectable({providedIn: 'root'})
export class MyService { ... }
这与:
完全相同export class MyService { ... }
和
import { MyService } from './path/to/my.service';
@NgModule({
...
providers: [MyService]
})
export class MyService { ... }
使用这种新语法是完全可选的,传统语法(使用 providers[] )仍然有效。 "new syntax" 确实提供了一个优势:服务可以通过 Angular 延迟加载(在幕后)并且可以自动删除冗余代码。这可以带来更好的性能和加载速度 - 尽管这通常只适用于更大的服务和应用程序。
来源:Udemy