当前位置: 移动技术网 > IT编程>脚本编程>AngularJs > Angular2 多级注入器详解及实例

Angular2 多级注入器详解及实例

2018年05月08日  | 移动技术网IT编程  | 我要评论

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.服务尽量是模块级,不是应用级。

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网