Współdzielenie tego samego elementu drzewa DI

Do tej pory naszym problemem jest to, że tworzymy dwa wystąpienia tych samych usług na różnych poziomach drzewa DI. Instancja utworzona w dolnej gałęzi drzewa jest dodatkowo zdefiniowana na poziomie katalogu głównego. Chcemy uniknąć tworzenia drugiej instancji na niższym poziomie drzewa DI dla modułu załadowanego z opóźnieniem i używać tylko instancji usługi zarejestrowanej w katalogu głównym drzewa.

Aby to osiągnąć, musimy zmodyfikować definicję SharedModule i zamiast definiować naszą usługę w własnościprovider, musimy stworzyć statyczną metodę o nazwie forRoot, która eksportuje usługę wraz z samym modułem.

app/shared/shared.module.ts

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CounterService } from './counter.service';

@NgModule({})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [CounterService]
    };
  }
}

Za pomocą tej konfiguracji możemy zaimportować ten moduł do naszego modułu głównego AppModule wywołującego metodęforRoot w celu zarejestrowania modułu i usługi.

app/app.module.ts

...
import { SharedModule } from './shared/shared.module';

@NgModule({
  imports: [
    SharedModule.forRoot(),
    ...
  ],
  ...
})
export class AppModule {}

Powinniśmy wywoływać forRoot tylko w głównym module aplikacji i nigdzie indziej. Gwarantuje to, że tylko jedna instancja usługi istnieje na poziomie katalogu głównego. Wywołanie forRoot w innym module może ponownie zarejestrować usługę na innym poziomie drzewa DI.

Ponieważ SharedModule zawiera tylko usługę, którą Angular rejestruje w iniektorze aplikacji root, nie musimy go importować doLazyModule. Jest tak dlatego, że załadowany z opóźnieniem moduł będzie już miał dostęp do usług zdefiniowanych na poziomie głównym.

Zobacz przykład [056]

Tym razem za każdym razem, gdy zmieniamy wartość właściwości 'counter', ta wartość jest dzielona między EagerComponent iLazyComponent, co potwierdza, że ​​używamy tego samego wystąpienia CounterService.

Jest jednak bardzo prawdopodobne, że możemy mieć komponent, potok lub dyrektywę zdefiniowaną w SharedModule, której potrzebujemy w innym module. Wykonaj na przykład następujące czynności .

app/shared/shared.module.ts

import { NgModule, ModuleWithProviders } from '@angular/core';
import { CounterService } from './counter.service';

import { HighlightDirective } from './highlight.directive';

@NgModule({
  declarations: [HighlightDirective],
  exports: [ HighlightDirective ]
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: SharedModule,
      providers: [CounterService]
    };
  }
}

Tutaj deklarujemy i eksportujemy HighlightDirective, aby inne moduły importująceSharedModule mogły używać go w swoich szablonach. Oznacza to, że możemy po prostu zaimportować moduł do LazyModule normalnie.

app/lazy/lazy.module.ts

import { NgModule } from '@angular/core';

import { SharedModule } from '../shared/shared.module';

import { LazyComponent }   from './lazy.component';
import { routing } from './lazy.routing';

@NgModule({
  imports: [
    SharedModule,
    routing
  ],
  declarations: [LazyComponent]
})
export class LazyModule {}

Teraz możemy użyć tej dyrektywy w LazyModule bez tworzenia kolejnej instancjiCounterService.

Zobacz przykład [057]