English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Spiegazione dettagliata e esempio di esempio dell'iniettore multilivello di Angular2

Angular2 include troppi contenuti nella dipendenza dell'iniezione, uno dei quali è l'iniettore, che è molto difficile da comprendere. Oggi non entreremo nel dettaglio dei contenuti dell'iniettore, ma si può fare riferimento alla documentazione ufficiale. Oggi parleremo del livello dell'iniettore.

Quindi, il contenitore che il componente utilizza per ottenere il servizio selezionerà quale tra essi.

Facciamo un breve introduzione di sfondo: ci sono 3 componenti AppComponent il componente radice, il componente DetailList (componente elenco log), il componente Detail (componente log).

Questi tre componenti formeranno un albero di componenti, e possiamo anche considerare che ogni componente avrà un iniettore indipendente (a volte non si verifica, ma possiamo pensare così).

Aggiungiamo un servizio di log LoggerService, se seguiamo il nostro modo di入门 comune, forniamo LoggerService nei Providers del modulo radice. Quindi in tutto l'applicazione, LoggerService avrà una sola istanza, cosa significa? Significa che in qualsiasi componente, l'istanza di LoggerService che otteniamo è la prima creata, tutti i componenti condividono un'istanza di servizio. Questo può essere un tratto utile, ad esempio per la configurazione globale che utilizziamo.

Univoco globale non è il punto chiave che dobbiamo verificare questa volta, perché è troppo comune. Questo che dobbiamo spiegare è come ottenere un'istanza di LoggerService separata in ogni componente, ossia ogni istanza del componente è diversa. Questo richiede una comprensione delle dipendenze di ng2.

Passiamo gradualmente a spiegare come farlo?

Per facilitare la comprensione di chi legge questo breve testo, ho aggiunto alcune basi di codice.

1.app.module.ts L'modulo radice dell'applicazione. Attenzione, non abbiamo registrato loggerService nei Providers. Certo, possiamo raggiungere lo stesso obiettivo tramite il metodo successivo.

import { NgModule, Optional, SkipSelf, ReflectiveInjector} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
/* App Root */
import { AppComponent } from './app.component';
import { routing } from './app.routing';
import { Title } from '@angular/platform-browser';
import {MessagesModule, GrowlModule, ButtonModule}from 'primeng/primeng';
import {AppDetailComponent}from './app-detail.component';
import {AppDetailListComponent}from './app-detailList.component';
import {LoggerService}from './logger.service';
let allTitle: string = "郭志奇";
@NgModule({
 imports: [
 BrowserModule,
 MessagesModule,
 GrowlModule, ButtonModule
 ],
 declarations: [AppComponent, AppDetailComponent, AppDetailListComponent],// Dichiarazione delle informazioni sui componenti necessari per il modulo corrente
 exports: [],
 providers: [Title],
 bootstrap: [AppComponent]
}
export class AppModule {
 constructor( @Optional() @SkipSelf() parentModule: AppModule) {
 console.log(parentModule);
 if (parentModule) {
  throw new Error;
  'AppModule è già caricato. Importalo solo nel AppModule');
 }
 }
}

2.app.component.ts - Componente radice dell'applicazione

import { Component, ViewEncapsulation, Host, ViewContainerRef, ReflectiveInjector } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Message } from 'primeng/primeng';
import {LoggerService}from './logger.service';
@Component({
 selector: 'my-app',
 moduleId: module.id,
 templateUrl: './app.component.html',
 providers: [
  { provide: LoggerService, useClass: LoggerService }
 ]
}
export class AppComponent {
 subtitle = '(Finale)';
 private msgs: Message[];
 constructor(private title: Title, @Host() private logger: LoggerService) {
  this.title.setTitle("AppComponent");
 }
 show(): void {
  this.logger.Debug();
 }
}

Attenzione, abbiamo registrato LoggerService nei providers del componente principale.

3.app.detailList.ts Anche nei providers della lista di log è registrato LoggerService

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'my-detailList',
 templateUrl: './app-detailList.component.html',
 moduleId: module.id,
 providers: [
  { provide: LoggerService, useClass: LoggerService }
 ]
}
export class AppDetailListComponent {
 constructor( private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

 4.app.detail.ts Il componente di log non ha registrato LoggerService nei providers.

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'detail',
 moduleId: module.id,
 templateUrl: './app-detail.component.html',
 providers: [
  // { provide: LoggerService, useClass: LoggerService }
 ]
}
export class AppDetailComponent {
 constructor( private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

 Ora vediamo la gerarchia di LoggerService con Chrome.

 

Visualizzando il grafico delle dipendenze, possiamo vedere che il componente AppComponent utilizza un LoggerService separato, il componente DetailList utilizza un'istanza di LoggerService separata, mentre il componente Detail utilizza l'istanza di LoggerService del componente padre DetailList.

Attualmente non raggiungiamo i nostri requisiti, i nostri requisiti sono che ogni componente abbia un'istanza di LoggerService separata, quindi supponiamo che i providers del componente Detail siano quelli che ci mancano, è difficile testare la causa. Quindi aggiungiamo un @Host() per limitare l'intervallo di ricerca dell'iniettore.

Per il metodo di ricerca upwards dell'iniettore, consultare la documentazione ufficiale.

Per facilitare il debug, abbiamo aggiunto @Host().

@Host decoratore limita la ricerca upwards alla componente host.

detail.ts Avvisa che il componente detail aggiunge il decoratore @Host().

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'detail',
 moduleId: module.id,
 templateUrl: './app-detail.component.html',
 providers: [
  // { provide: LoggerService, useClass: LoggerService }
 ]
}
export class AppDetailComponent {
 constructor( @Host() private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

Verrà visualizzato un messaggio di errore che dice di non trovare l'istanza di LoggerService, l'azione di @Host() è quella di limitare l'indicatore a trovare il componente corrente e non continuare a cercare oltre. Quindi apparirà l'errore di non trovare Providers.

Il risultato ottenuto con providers è quello che volevamo.

 

Ha risolto perfettamente il problema dell'uso di istanze di servizio separate per componenti multipli.

 Sommario:

1. Se si desidera utilizzare il servizio del componente in modo indipendente, è necessario registrare il servizio in modo indipendente nei providers. È facile da capire

2. Per una migliore rilevazione dei problemi potenziali, aggiungere il decoratore @Host() al servizio del componente, che può lanciare tempestivamente messaggi di errore

3. Utilizzare lo strumento di debug di ng2

4. E' necessario chiarire le relazioni tra i vari componenti, perché le diverse relazioni tra i componenti possono causare istanze di servizio diverse

5. Il servizio dovrebbe essere di livello modulo, non di livello applicazione.

Grazie per la lettura, spero che possa aiutare tutti, grazie per il supporto al nostro sito!

Ti potrebbe interessare