Angular 应用开发里使用 ForRoot 解决 Lazy Loaded Module 里单例行为丢失的问题

简介: Angular 应用开发里使用 ForRoot 解决 Lazy Loaded Module 里单例行为丢失的问题



笔者在 Angular 实际项目开发中曾经遇到这样一个需求:


我们想创建一个共享模块,它将包含一个配置来设置布尔值(作为标志)以启用或禁用其他模块的某些功能。 其他模块可以在 Angular 应用程序的引导期间加载,也可以是延迟加载的模块。


ForRoot 的使用场景

当我们想要跨应用程序维护服务的单个实例(单例)时使用,这些应用程序也将具有延迟加载的模块。


举个例子,看看托管在 StackBlitz 上这个演示代码,其中计数器对于急切和延迟加载模块的行为不同。


image.png


sharedModule 的 provider 数组里导入了这个服务:


image.png


在此示例中,我们共享一项服务以跟上计数器值。 每次任何组件增加存储在计数器服务中的值时,我都想与所有组件共享它。


我在 app.routes.ts 里定义了一个路由数组 routing:


image.png


上图通过 LazyLoad 的方式,加载 LazyModule,后者的实现:


image.png


LazyModule 导入 SharedModule,是为了使用其计数器 CounterService:


image.png

问题是当我们尝试引入延迟加载模块时。 请注意延迟加载的组件如何不共享相同的计数器值。 当仅使用预加载组件时,如果您使用共享服务,下面的示例将起作用,但请注意延迟加载组件的行为方式。惰性组件获取自己的服务实例。


但这个解决方案的问题是:我们在 Eager Load 的 Component 里点击 Counter 按钮,增加计数器的值后,点击 Lazy 超链接,进入 LazyModule 里的 Component,我们期望此时在 Component 里显示的值也为 7:


image.png


然而事与愿违,Lazy Component 里的值为 0:


image.png


计数器由驻留在 SharedModule 下的 CounterService 维护。 由于延迟加载的模块创建了自己的服务实例,我们失去了 Angular 服务的单例行为。


为了解决这个问题,我们需要引入 forRoot() 的概念。 可以在这个演示中看到工作示例。这是同样的原因,我们将它与 RouterModule 一起使用,以帮助 RouterService 了解具有多个模块的应用程序行为。


RouterModule.forRoot(ROUTES)


修改后的解决方案,SharedModule 的实现代码:


import { NgModule, ModuleWithProviders } from '@angular/core';
import { CounterService } from './counter.service';
@NgModule({
})
export class SharedModule {
    static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [ CounterService ]
    }
  }
}



App module 里调用这个方法:


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { SharedModule } from './shared/shared.module';
import { AppComponent } from './app.component';
import { EagerComponent } from './eager.component';
import { routing } from './app.routes';
@NgModule({
  imports:      [ BrowserModule, SharedModule.forRoot(), routing ],
  declarations: [ AppComponent, EagerComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }


修改之后的代码链接。


之后可以在 Eager Load 和 Lazy Load Component 之间任意切换,单例模式的行为能够正常工作。


image.png


参考文献

https://medium.com/slackernoon/when-to-use-angulars-forroot-method-400094a0ebb7


https://shashankvivek-7.medium.com/forroot-injectiontoken-in-action-angular-c2bab9959207


https://stackoverflow.com/questions/40498081/routermodule-forrootroutes-vs-routermodule-forchildroutes


https://angular.io/guide/lazy-loading-ngmodules#forroot-and-forchild



相关文章
|
11月前
|
Web App开发 前端开发 JavaScript
Angular 应用实现 Lazy Load(懒加载)的项目实战经验分享
Angular 应用实现 Lazy Load(懒加载)的项目实战经验分享
|
12月前
|
设计模式 SQL 关系型数据库
Proxy Facade 在 Angular 应用 Lazy Load 中的作用
Proxy Facade 在 Angular 应用 Lazy Load 中的作用
|
12月前
|
前端开发 JavaScript UED
Angular 应用 Lazy Loading 设计概述
Angular 应用 Lazy Loading 设计概述
|
12月前
|
UED
Angular 中的 code splitting 和 lazy loading 技术
Angular 中的 code splitting 和 lazy loading 技术
|
12月前
|
JavaScript 前端开发 开发者
实现 Angular Lazy loading 时应该避免 Static Imports 的原因
实现 Angular Lazy loading 时应该避免 Static Imports 的原因
|
12月前
|
UED
Angular 中 Lazy Loading 的陷阱与最佳实践
Angular 中 Lazy Loading 的陷阱与最佳实践
|
12月前
关于 Angular Lazy loaded modules 中的 providers
关于 Angular Lazy loaded modules 中的 providers
|
12月前
|
JavaScript 前端开发
如何对 Angular Lazy Loaded Module 进行 Customization
如何对 Angular Lazy Loaded Module 进行 Customization
Angular 应用开发里使用 ForRoot 解决 Lazy Loaded Module 里单例行为丢失的问题
Angular 应用开发里使用 ForRoot 解决 Lazy Loaded Module 里单例行为丢失的问题
Angular Lazy Load 的一个局限性以及解决办法
Angular Lazy Load 的一个局限性以及解决办法
Angular Lazy Load 的一个局限性以及解决办法