angular2 的依赖注入
angular2 的依赖注入包含了太多的内容,其中的一个重点就是注入器,而注入器又非常难理解,今天我们不深入介绍注入器的内容,可以参考官方文档,我们今天来说注入器的层级。
也就是组件获取服务的容器会选择具体哪一个。
先简单介绍一个背景:有3个组件AppComponent 根组件、DetailList组件 ( 日志列表组件)、Detail组件( 日志组件)。
这三个组件会形成一个组件树,对应的我们也可以认为每个组件都会有一个独立的注入器(有时候不会出现,但是可以这么认为)。
加入一个日志服务LoggerService,如果按照我们普通的入门方式,在根模块providers 中提供LoggerService。那么在整个应用程序中,LoggerService只有一个实例,什么意思呢?就是说无论在哪个组件,获取到的都是首次创建的LoggerService,所有组件共用一个服务实例,这有时候会是一个有用的特性,比如我们使用的全局配置。
全局唯一不是我们这次要验证的重点,因为这个太普通,我们这次要说明的是我们如何在每个组件中都获取单独的LoggerService实例,即每个组件的实例都不同。这个就需要对ng2的依赖注入有所了解才可以。
我们逐步来说明如何实现?
为了便于看到这篇短文的同学有所了解,我加入一些基础代码。
1.app.module.ts 应用程序根模块。注意此处我们没有在Providers中注册loggerService。当然注册了通过后面的方法也可以达到我们的目的。
1 import { NgModule, Optional, SkipSelf, ReflectiveInjector} from '@angular/core';
2 import { BrowserModule } from '@angular/platform-browser';
3
4 /* App Root */
5 import { AppComponent } from './app.component';
6 import { routing } from './app.routing';
7 import { Title } from '@angular/platform-browser';
8 import {MessagesModule, GrowlModule, ButtonModule}from 'primeng/primeng';
9 import {AppDetailComponent}from './app-detail.component';
10 import {AppDetailListComponent}from './app-detailList.component';
11 import {LoggerService}from './logger.service';
12 let allTitle:string="郭志奇";
13
14 @NgModule({
15 imports: [
16 BrowserModule,
17 MessagesModule,
18 GrowlModule, ButtonModule
19 ],
20 declarations: [AppComponent, AppDetailComponent, AppDetailListComponent],//声明当前模块需要的指定 组件信息
21 exports: [],
22 providers: [Title],
23 bootstrap: [AppComponent]
24 })
25 export class AppModule {
26 constructor( @Optional() @SkipSelf() parentModule: AppModule) {
27 console.log(parentModule);
28 if (parentModule) {
29 throw new Error(
30 'AppModule is already loaded. Import it in the AppModule only');
31 }
32 }
33 }
2.app.component.ts 应用程序根组件
1 import { Component, ViewEncapsulation, Host, ViewContainerRef, ReflectiveInjector } from '@angular/core';
2 import { Title } from '@angular/platform-browser';
3 import { Message } from 'primeng/primeng';
4 import {LoggerService}from './logger.service';
5 @Component({
6 selector: 'my-app',
7 moduleId: module.id,
8 templateUrl: './app.component.html',
9 providers: [
10 { provide: LoggerService, useClass: LoggerService }
11 ]
12 })
13 export class AppComponent {
14 subtitle = '(Final)';
15 private msgs: Message[];
16 constructor(private title: Title, @Host() private logger: LoggerService) {
17 this.title.setTitle("AppComponent");
18 }
19
20 show(): void {
21 this.logger.Debug();
22 }
23 }
请注意,我们在跟组件中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。
1 import {Component, Host}from '@angular/core';
2 import {LoggerService}from './logger.service';
3 @Component({
4 selector: 'detail',
5 moduleId: module.id,
6 templateUrl: './app-detail.component.html',
7 providers: [
8 // { provide: LoggerService, useClass: LoggerService }
9 ]
10 })
11
12 export class AppDetailComponent {
13 constructor( private logger: LoggerService) {
14
15 }
16 show(): void {
17 this.logger.Debug();
18 }
19
20 }
现在我们通过chrome来看一下 LoggerService的层级关系。
通过查看依赖关系图,我们可以看到AppComponent组件使用了单独的LoggerService,DetailList组件也使用单独的LoggerService 实例,而Detail组件使用的是父组件DetailList的LoggerService实例。
目前来看没有达到我们的要求,我们的要求是每个组件都有单独的LoggerService实例,那么我们假设Detail组件的providers是我们忘记输入的,很难测试出原因所在。那么我们加入一个@Host()来限制注入器的查找范围。
对于注入器的向上查找方式,请参考官方文档。
为了便于调试,我们加入@Host().
@Host
装饰器将把往上搜索的行为截止在 宿主组件
detail.ts 提示detail组件加入@Host()装饰器
1 import {Component, Host}from '@angular/core';
2 import {LoggerService}from './logger.service';
3 @Component({
4 selector: 'detail',
5 moduleId: module.id,
6 templateUrl: './app-detail.component.html',
7 providers: [
8 // { provide: LoggerService, useClass: LoggerService }
9 ]
10 })
11
12 export class AppDetailComponent {
13 constructor( @Host() private logger: LoggerService) {
14
15 }
16 show(): void {
17 this.logger.Debug();
18 }
19
20 }
会提示找不到LoggerService的实例,@Host()的作用就是限制注入器查找到当前组件就停止,不会继续往上查找。所以会出现找不到Providers的错误。
加上providers 的结果就是我们想要的了。
完美的解决了多组件使用单独服务实例的问题。
总结:
1.如果要使组件单独使用服务,那么首先要在providers 中单独注册该服务。很容易理解
2.为了更好的检测可能出现的问题,在组件服务上加入@Host()装饰器,可以尽量早的抛出错误信息
3.使用ng2的debug工具
4.要明确各组件之间的关系,因为不同的组件关系会导致服务的实例的不同
5.服务尽量是模块级,不是应用级。
angular2,一个值得学习的东西。
angular2 的依赖注入的更多相关文章
- angular2的依赖注入
更好阅读体验,请看原文 在读这篇文章之前,你要先了解一下什么是依赖注入,网上关于这个的解释很多,大家可以自行Google. 我们这一篇文章还是以QuickStart项目为基础,从头开始讲解怎么在Ang ...
- angular2系列教程(八)In-memory web api、HTTP服务、依赖注入、Observable
大家好,今天我们要讲是angular2的http功能模块,这个功能模块的代码不在angular2里面,需要我们另外引入: index.html <script src="lib/htt ...
- Angular2 依赖注入
1. 使用DI 依赖注入是一个很重要的程序设计模式. Angular 有自己的依赖注入框架,离开了它,我们几乎没法构建 Angular 应用.它使用得非常广泛,以至于几乎每个人都会把它简称为 DI. ...
- angular2 学习笔记 ( DI 依赖注入 )
refer : http://blog.thoughtram.io/angular/2016/09/15/angular-2-final-is-out.html ( search Dependency ...
- 迈向angularjs2系列(5):依赖注入
一: 为什么要依赖注入 1.构造器引入依赖 假设一个类Car类依赖于Engine(引擎)类.Transition(变速箱)类,可使用构造器来完成. //类似如下代码 class Engine{} cl ...
- webapi - 使用依赖注入
本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity:由于快过年这段时间打算 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
- 在WPF中使用依赖注入的方式创建视图
在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...
- MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息
MVVM模式解析和在WPF中的实现(六) 用依赖注入的方式配置ViewModel并注册消息 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二 ...
随机推荐
- 准备开始自己搞企业管理软件,从openerp入手
公司运行了半年多,人还比较少,只用了一些即时通讯工具,还有svn等基本的工具 记账用的是gnucash 其他的管理急需相应的软件,找了很长时间也没有合适的 想了想,还是从开源的openerp odoo ...
- Python简史
Python简史 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Python是我喜欢的语言,简洁,优美,容易使用.前两天,我很激 ...
- 【BZOJ1007】【HNOI2008】水平可见直线
依旧看黄学长代码,不过这回是看完后自己写的 原题: 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.例 ...
- cve-2015-1635 poc
import socket import random ipAddr = "10.1.89.20" hexAllFfff = " req1 = "GET / H ...
- Nanopore sensors for nucleic acid analysis 论文阅读笔记
Nanopore sensors for nucleic acid analysis Bala Murali Venkatesan and Rashid Bashir 用于核酸分析的纳米孔传感器 纳米 ...
- 【转载】使用LFM(Latent factor model)隐语义模型进行Top-N推荐
最近在拜读项亮博士的<推荐系统实践>,系统的学习一下推荐系统的相关知识.今天学习了其中的隐语义模型在Top-N推荐中的应用,在此做一个总结. 隐语义模型LFM和LSI,LDA,Topic ...
- sql server 常用的系统存储过程
系统存储过程 说明 sp_databases 列出服务上的所有数据库 sp_helpdb 报告有关指定数据库或所有数据库的信息 sp_renamedb 更改数据库的名称 sp_tables 返回当 ...
- 虚拟化之vmx配置文件
https://www.haiku-os.org/get-haikuhttp://sanbarrow.com/vmx.html contradictionn. 矛盾:否认:反驳homegrownadj ...
- linux概念之/etc
[Thu Apr 02 15:04:32 1028 /dev/pts/0 192.168.2.250 /etc]#ll |grep -v "^d"|wc -l99[Thu Apr ...
- USACO/friday
Friday the Thirteenth 黑色星期五 描述 13号又是一个星期五.13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数.给出N年的 ...