English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Вложенная инъекция в angular2 охватывает слишком много контента, одним из ключевых аспектов является инъектор, который также очень сложен для понимания. Сегодня мы не будем углубляться в контент инъектора, можно参阅 официальную документацию, сегодня мы поговорим о иерархии инъекторов.
Это означает, что контейнер, который��取服务组件, выберет конкретный из них.
Прежде всего简要介绍一下背景: у нас есть 3 компонента AppComponent корневой компонент, Component DetailList (компонент списка логов), Component Detail (компонент логов).
Эти три компонента形成一个 компонентное дерево, и, соответственно, мы можем считать, что у каждого компонента будет отдельный инъектор (иногда он не появляется, но можно так думать).
Добавление сервис LoggerService, если следовать обычному методу入门ного уровня, предоставлять LoggerService в providers корневого модуля. Тогда в течение всего приложения, LoggerService будет единственным экземпляром, что означает? Это означает, что независимо от того, в каком компоненте, полученный LoggerService будет тем, который был создан в первый раз, все компоненты делят один сервисный экземпляр, это иногда может быть полезной функцией, например, для использования глобальной конфигурации.
Глобально уникальный не является нашим основным акцентом в этом разе, потому что это слишком обычное. В этот раз мы будем объяснять, как мы можем получить отдельный экземпляр LoggerService в каждом компоненте, то есть каждый компонент имеет свой уникальный экземпляр. Для этого необходимо иметь представление о зависимости инъекции ng2.
Мы будем постепенно объяснять, как это сделать?
Для того чтобы студенты, которые видят эту короткую статью, могли понять, я добавил некоторые базовые коды.
1.app.module.ts Приложение корневой модуль. Обратите внимание, что мы не зарегистрировали loggerService в Providers. Конечно, регистрация через后面的 метод также достигает нашей цели.
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],//Указание информации о компонентах, необходимых для текущего модуля exports: [], providers: [Title], bootstrap: [AppComponent] } export class AppModule { constructor( @Optional() @SkipSelf() parentModule: AppModule) { console.log(parentModule); if (parentModule) { throw new Error; 'AppModule уже загружен. Импортируйте его только в AppModule'); } } }
2.app.component.ts Приложение корневой компонент
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(); } }
Обратите внимание, что мы зарегистрировали LoggerService в providers корневого компонента.
3.app.detailList.ts: в providers списка логических записей также зарегистрирован 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: компонент providers логического компонента не зарегистрировал 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(); } }
Теперь давайте посмотрим на иерархию LoggerService через chrome.
Просмотр Dependence Diagram показывает, что компонент AppComponent использует отдельный экземпляр LoggerService, компонент DetailList также использует отдельный экземпляр LoggerService, а компонент Detail использует экземпляр LoggerService родительского компонента DetailList.
На данный момент это не соответствует нашим требованиям. Наши требования заключаются в том, чтобы у каждого компонента был отдельный экземпляр LoggerService. Тогда мы предположим, что providers компонента Detail мы забыли ввести, поэтому трудно определить причину. Тогда мы добавляем @Host() для ограничения диапазона поиска инъектора.
Для поиска в направлении инъектора, пожалуйста, обратитесь к официальной документации.
Для удобства отладки мы добавляем @Host().
@Host декоратор ограничивает поведение поиска до компонента-хозяина.
detail.ts: компонент detail добавляет декоратор @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(); } }
Будет отображаться сообщение об ошибке, что не найден экземпляр LoggerService. Функция @Host() заключается в том, чтобы ограничить поиск инъектором только текущим компонентом, а не продолжать вверх, поэтому会出现 ошибка, что не найдены Providers.
Результат с использованием providers именно тот, который мы хотели.
Перфекто解决了多组件使用单独服务实例的问题。
Обобщение:
1. Если нужно использовать компонент в отдельности с сервисом, сначала зарегистрируйте этот сервис отдельно в providers. Это легко понять
2. Для лучшего обнаружения возможных проблем добавьте декоратор @Host() к компонентным службам, чтобы можно было как можно раньше выводить сообщения об ошибках
3. Использование отладочных инструментов ng2
4. Необходимо четко определить отношения между компонентами, так как различные отношения компонентов могут привести к различным экземплярам служб.
5. Услуги должны быть модульными, а не прикладными.
Спасибо за чтение, надеюсь, это поможет вам, спасибо за поддержку нашего сайта!