Angular2 多级注入器详解及实例  更新时间:2016年10月30日 09:47:53   投稿:lqh   这篇文章主要介绍了Angular2 多级注入器详解的相关资料,并附简单实例代码,需要的朋友可以参考下 angular2 的依赖注入包含了太多的内容,其中的一个重点就是注入器,而注入器又非常难理解,今天我们不深入介绍注入器的内容,可以参考官方文档,我们今天来说注入器的层级。 也就是组件获取服务的容器会选择具体哪一个。 先简单介绍一个背景:有3个组件AppComponent 根组件、DetailList组件 ( 日志列表组件)、Detail组件( 日志组件)。 这三个组件会形成一个组件树,对应的我们也可以认为每个组件都会有一个独立的注入器(有时候不会出现,但是可以这么认为)。 加入一个日志服务LoggerService,如果按照我们普通的入门方式,在根模块providers 中提供LoggerService。那么在整个应用程序中,LoggerService只有一个实例,什么意思呢?就是说无论在哪个组件,获取到的都是首次创建的LoggerService,所有组件共用一个服务实例,这有时候会是一个有用的特性,比如我们使用的全局配置。 全局唯一不是我们这次要验证的重点,因为这个太普通,我们这次要说明的是我们如何在每个组件中都获取单独的LoggerService实例,即每个组件的实例都不同。这个就需要对ng2的依赖注入有所了解才可以。 我们逐步来说明如何实现? 为了便于看到这篇短文的同学有所了解,我加入一些基础代码。 1.app.module.ts 应用程序根模块。注意此处我们没有在Providers中注册loggerService。当然注册了通过后面的方法也可以达到我们的目的。 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 is already loaded. Import it in the AppModule only’); } } } 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(); } } 请注意,我们在跟组件中providers中注册了LoggerService。 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(); } }  现在我们通过chrome来看一下 LoggerService的层级关系。   通过查看依赖关系图,我们可以看到AppComponent组件使用了单独的LoggerService,DetailList组件也使用单独的LoggerService 实例,而Detail组件使用的是父组件DetailList的LoggerService实例。 目前来看没有达到我们的要求,我们的要求是每个组件都有单独的LoggerService实例,那么我们假设Detail组件的providers是我们忘记输入的,很难测试出原因所在。那么我们加入一个@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的debug工具 4.要明确各组件之间的关系,因为不同的组件关系会导致服务的实例的不同 5.服务尽量是模块级,不是应用级。 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持! 您可能感兴趣的文章: Angular2表单自定义验证器的实现 Angular2 NgModule 模块详解 Angular2中Bootstrap界面库ng-bootstrap详解 Angular2 环境配置详细介绍 详解Angular2中的编程对象Observable 深入理解Angular2 模板语法 Angular2内置指令NgFor和NgIf详解 angular2使用简单介绍 Angular2 多级注入器 相关文章 AngularJs 国际化(I18n/L10n)详解 本文主要介绍AngularJs 国际化的知识,这里整理了详细的资料来讲解国际化,有需要的小伙伴可以参考下 2016-09-09 AngularJS ng-table插件设置排序 这篇文章主要介绍了AngularJS ng-table插件设置排序的相关资料,需要的朋友可以参考下 2016-09-09 Ubuntu系统下Angularjs开发环境安装 本文主要介绍 Ubuntu系统下Angularjs开发环境安装,这里详细介绍了安装步骤和注意事项,有在Ubuntu 环境下开发的朋友可以参考下 2016-09-09 基于Angularjs-router动态改变Title值的问题 今天小编就为大家分享一篇基于Angularjs-router动态改变Title值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 2018-08-08 Angularjs的ng-repeat中去除重复数据的方法 这篇文章主要介绍了Angularjs的ng-repeat中去除重复数据的方法,涉及AngularJS针对重复数据的遍历与过滤技巧,需要的朋友可以参考下 2016-08-08 AngularJs解决跨域问题案例详解(简单方法) 本文通过一个案例给大家介绍angularJs解决跨域问题,非常具有参考借鉴价值,感兴趣的朋友一起学习吧 2016-05-05 详解支持Angular 2的表格控件 本文主要对支持Angular2的表格控件进行详细介绍。具有一定的参考价值,下面跟着小编一起来看下吧 2017-01-01 angularjs使用directive实现分页组件的示例 本篇文章主要介绍了angularjs使用directive实现分页组件的示例,具有一定的参考价值,有兴趣的可以了解一下。 2017-02-02 Angular.js ng-file-upload结合springMVC的使用教程 这篇文章主要给大家介绍了关于Angular.js文件上传控件ng-file-upload结合springMVC的使用教程,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。 2017-07-07 简单谈谈关于Angular Cli打包的事 使用过angular2人都应该知道,angular2提供的Angular CLI来快速搭建,快速生成serives、component、derective、modulet各种模板…下面这篇文章主要给大家介绍了关于Angular Cli打包的一些事,需要的朋友可以参考下。 2017-09-09 最新评论

angular2 的依赖注入包含了太多的内容,其中的一个重点就是注入器,而注入器又非常难理解,今天我们不深入介绍注入器的内容,可以参考官方文档,我们今天来说注入器的层级。

也就是组件获取服务的容器会选择具体哪一个。

先简单介绍一个背景:有3个组件AppComponent 根组件、DetailList组件 ( 日志列表组件)、Detail组件( 日志组件)。

这三个组件会形成一个组件树,对应的我们也可以认为每个组件都会有一个独立的注入器(有时候不会出现,但是可以这么认为)。

加入一个日志服务LoggerService,如果按照我们普通的入门方式,在根模块providers 中提供LoggerService。那么在整个应用程序中,LoggerService只有一个实例,什么意思呢?就是说无论在哪个组件,获取到的都是首次创建的LoggerService,所有组件共用一个服务实例,这有时候会是一个有用的特性,比如我们使用的全局配置。

全局唯一不是我们这次要验证的重点,因为这个太普通,我们这次要说明的是我们如何在每个组件中都获取单独的LoggerService实例,即每个组件的实例都不同。这个就需要对ng2的依赖注入有所了解才可以。

我们逐步来说明如何实现?

为了便于看到这篇短文的同学有所了解,我加入一些基础代码。

1.app.module.ts 应用程序根模块。注意此处我们没有在Providers中注册loggerService。当然注册了通过后面的方法也可以达到我们的目的。

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 is already loaded. Import it in the AppModule only');
 }
 }
}

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

请注意,我们在跟组件中providers中注册了LoggerService。

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

}

 现在我们通过chrome来看一下 LoggerService的层级关系。

 

通过查看依赖关系图,我们可以看到AppComponent组件使用了单独的LoggerService,DetailList组件也使用单独的LoggerService 实例,而Detail组件使用的是父组件DetailList的LoggerService实例。

目前来看没有达到我们的要求,我们的要求是每个组件都有单独的LoggerService实例,那么我们假设Detail组件的providers是我们忘记输入的,很难测试出原因所在。那么我们加入一个@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的debug工具

4.要明确各组件之间的关系,因为不同的组件关系会导致服务的实例的不同

5.服务尽量是模块级,不是应用级。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

您可能感兴趣的文章:

  • Angular2表单自定义验证器的实现
  • Angular2 NgModule 模块详解
  • Angular2中Bootstrap界面库ng-bootstrap详解
  • Angular2 环境配置详细介绍
  • 详解Angular2中的编程对象Observable
  • 深入理解Angular2 模板语法
  • Angular2内置指令NgFor和NgIf详解
  • angular2使用简单介绍
张贴在3