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

Angular2 Descripción detallada del inyector de múltiples niveles y ejemplos

angular2 Inyección de dependencias contiene demasiado contenido, uno de los puntos clave es el inyector, y el inyector es muy difícil de entender. Hoy no profundizaremos en el contenido del inyector, puede referirse a la documentación oficial, hoy hablaremos de la jerarquía del inyector.

es decir, el contenedor de servicios del componente elegirá cuál.

Presentemos brevemente un contexto: hay3Componentes: AppComponent (componente raíz), DetailList componente (componente de lista de registro), Detail componente (componente de registro).

Estos tres componentes formarán un árbol de componentes, y también podemos considerar que cada componente tendrá un inyector independiente (a veces no aparece, pero podemos pensar así).

Añadir un servicio de registro LoggerService, si seguimos la forma de入门 común, proporcionamos LoggerService en providers del módulo raíz. Entonces, en toda la aplicación, LoggerService solo tiene una instancia, ¿qué significa eso? Es decir, independientemente de qué componente, el LoggerService obtenido es el primero creado, todos los componentes comparten una instancia de servicio, esto a veces puede ser una característica útil, como la configuración global que usamos.

global es único y no es el punto principal de nuestra verificación esta vez, porque es demasiado común. Lo que queremos explicar esta vez es cómo obtenemos una instancia única de LoggerService en cada componente, es decir, cada instancia de componente es diferente. Esto requiere entender ng2de inyección de dependencias.

Vamos a explicar paso a paso cómo hacerlo?

Para facilitar la comprensión de los estudiantes que lean este artículo, he agregado algunos códigos básicos.

1.app.module.ts Aplicación raíz del módulo. Nota: no hemos registrado loggerService en Providers. Claro, también podemos lograr nuestro objetivo con el método posterior.

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],//Declarar la información específica del componente necesaria para el módulo actual
 exports: [],
 providers: [Title],
 bootstrap: [AppComponent]
})
export class AppModule {
 constructor( @Optional() @SkipSelf() parentModule: AppModule) {
 console.log(parentModule);
 if (parentModule) {
  throw new Error(
  'AppModule ya está cargado. Sólamente importarlo en AppModule');
 }
 }
}

2.app.component.ts  Aplicación raíz del componente

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 = '(Final)';
 private msgs: Message[];
 constructor(private title: Title, @Host() private logger: LoggerService) {
  this.title.setTitle("AppComponent");
 }
 show(): void {
  this.logger.Debug();
 }
}

Tenga en cuenta que hemos registrado LoggerService en los providers del componente raíz.

3.app.detailList.ts El componente de lista de registro también ha registrado LoggerService en providers.

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 El componente de registro no ha registrado LoggerService.

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();
 }
}

 Ahora vamos a ver la relación jerárquica de LoggerService en Chrome.

 

Mirando el diagrama de dependencias, podemos ver que el componente AppComponent utiliza LoggerService separado, el componente DetailList también utiliza una instancia separada de LoggerService, y el componente Detail utiliza la instancia de LoggerService del componente padre DetailList.

Hasta ahora no hemos alcanzado nuestros requisitos, nuestros requisitos son que cada componente tenga una instancia separada de LoggerService, por lo que suponemos que los providers del componente Detail son los que hemos olvidado ingresar, es difícil probar la causa. Entonces, añadimos un @Host() para limitar el rango de búsqueda del inyector.

Para la forma de búsqueda hacia arriba del inyector, consulte el documento oficial.

Para facilitar la depuración, hemos añadido @Host().

@Host decorador detiene la búsqueda hacia arriba en el componente anfitrión

detail.ts Avisa que el componente detail se añade el decorador @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();
 }
}

Se sugerirá que no se puede encontrar la instancia de LoggerService, el papel de @Host() es limitar que el inyector busque hasta el componente actual y no siga buscando

El resultado de agregar providers es lo que queremos.

 

Ha resuelto perfectamente el problema de que varios componentes utilicen instancias de servicios separadas.

 Resumen:

1.Si se desea que el componente utilice el servicio por separado, primero debe registrarse el servicio por separado en providers. Es fácil de entender

2.Para detectar mejor los posibles problemas, se puede agregar el decorador @Host() en el servicio de componentes, lo que puede lanzar información de errores lo antes posible

3.Usar ng2de herramientas de debug

4.Debería aclararse la relación entre los componentes, ya que diferentes relaciones de componentes pueden causar que las instancias del servicio sean diferentes

5.El servicio debe ser de nivel de módulo, no de nivel de aplicación.

Gracias por leer, espero que pueda ayudar a todos, gracias por el apoyo a nuestro sitio!

Te gustará