在Angular中使用依赖注入(DI)的时候,我们一般会使用providers。其实要做同样的事我们还有另外一个选择:viewProviders

viewProviders允许我们定义只对组件的view可见的provider。下面我们用例子详细的说明这一点。

假设我们有一个简单的服务:

// myService.service.ts
import { Injectable } from '@angular/core'; @Injectable()
export class MyService{
testIfGetService(where){
console.log('Got My Service in ' + where);
}
}

这个服务很简单,只需要打印出在哪里调用了该服务。

然后有一个子组件,是用来投射到父组件里面的(等会将会看到):

// child.component.ts
import { Component } from '@angular/core';
import { MyService } from './myService.service'; @Component({
selector: 'vp-child',
template: `
<div>This is child!!!</div>
`
})
export class VPChild{
constructor(
private service: MyService
){
this.service.testIfGetService('child');
}
}

这个组件注入了MyService服务,调用MyServicetestIfGetService方法,并传入child表明这是在child组件调用的。

还有另外一个子组件,这个组件是用来放在父组件的模板(template)里面的:

// viewChild.component.ts
import { Component } from '@angular/core';
import { MyService } from './myService.service'; @Component({
selector: 'vp-viewchild',
template: `
<div>This is viewChild!!!</div>
`
})
export class ViewVPChild{
constructor(
private service: MyService
){
this.service.testIfGetService('viewChild');
}
}

这里同样注入MyService服务,调用MyService服务的testIfGetService方法,并传入viewChild

最后是父组件:

// parent.component.ts
import { Component } from '@angular/core';
import { MyService } from './myService.service';
@Component({
selector: 'vp-parent',
template: `
<div>This is parent!!!</div>
<ng-content></ng-content>
<vp-viewchild></vp-viewchild>
`,
providers: [MyService]
})
export class VPParent{
constructor(
private service: MyService
){
this.service.testIfGetService('parent');
}
}

在父组件,用providers注册MyService,然后调用MyServicetestIfGetService传入parent

然后就像这样使用父组件:

<vp-parent>
<vp-child></vp-child>
</vp-parent>

运行程序,控制台打印出了结果:

一切就像预期那样!!

然后,我们用viewProviders代替providers注册MyService,看看会发生什么:

// parent.component.ts
import { Component } from '@angular/core';
import { MyService } from './myService.service';
@Component({
selector: 'vp-parent',
template: `
<div>This is parent!!!</div>
<ng-content></ng-content>
<vp-viewchild></vp-viewchild>
`,
viewProviders: [MyService] // <---
})
export class VPParent{
constructor(
private service: MyService
){
this.service.testIfGetService('parent');
}
}

这样修改之后,运行程序,发现报错了:

如果把contentChild注释掉,就像这样:

<vp-parent>
<!-- <vp-child></vp-child> -->
</vp-parent>

是不会报错的:

这就说明,在父组件用viewProviders注册的provider,对contentChildren是不可见的。而使用providers注册的provider,对viewChildren和contentChildren都可见!

补充说明:组件会逐级向上寻找provider,直到找到为止,否则就会抛出错误。就像这里:

<vp-parent>
<vp-child></vp-child>
</vp-parent>

vp-child往上找MyService的provider,结果在vp-parent找到了。但是在用viewProviders的时候,vp-child往上找,也就是到vp-parent,结果没找到,然后又去找vp-parent的父级,还是没找到(因为在这个例子里,我们只在vp-parent注册了MyService),然后又继续往上找……如此找到边界也没找到,所以抛出了一个错误。如果你不希望这样,可以使用@Host做出限制,就像这样:

constructor(
@Host() private service: MyService
){}

关于@Host()本文不作展开,有兴趣可以自行google。

Angular:ViewProviders和Providers的区别的更多相关文章

  1. [Angular] Difference between Providers and ViewProviders

    For example we have a component: class TodoList { private todos: Todo[] = []; add(todo: Todo) {} rem ...

  2. [Angular 2] Value Providers & @Inject

    Dependecies aren’t always objects created by classes or factory functions. Sometimes, all we really ...

  3. [Angular 2] BYPASSING PROVIDERS IN ANGULAR 2

    Artical --> BYPASSING PROVIDERS IN ANGULAR 2 Here trying to solve one problem: On the left hand s ...

  4. [Angular] Pipes as providers

    In this example, we are going to see how to use Pipe as providers inject into component. We have the ...

  5. angular $observe() 和$watch的区别

    1.$observe()是属性attributes的方法,只能在DOM属性的值发生变化时用,并且只用于directive内. 当需要监听一个包含变量的属性值时attr1="Name:{{na ...

  6. angular js jquery中post请求的一点小区别

    这也是最近遇到的坑,还是之前那个项目,现在要实现登录功能. 背景:注册功能之前已经跑通了.前端用的是jquery后台是springMVC.鉴于注册和登录有些接口功能是类似的(比如注册确保邮箱是没有注册 ...

  7. angular学习—组件

    组件: vue组件:xxx.vue react组件:xxx.js+xxx.css angular组件:xxx.ts+xxx.css+xxx.html angular的装饰器: @ngModule:an ...

  8. quora 中有关angular与emberjs的精彩辩论

    原贴地址,要注册才能看,这里只有国人翻译的一部分内容 本文源自于Quora网站的一个问题,作者称最近一直在为一个新的Rails项目寻找一个JavaScript框架,通过筛选,最终纠结于Angular. ...

  9. Angular.js vs Ember.js

    Angular.js 拥抱 HTML/CSS Misko Hevery(Angular.js的开发者之一)回答了这一问题,他的主要观点如下: 在HTML中加入太多逻辑不是好做法.Angular.js只 ...

随机推荐

  1. 解决ubuntu18.04使用vi编辑器方向键错乱

    1.编辑 vimrc.tiny 文件 vi /etc/vim/vimrc.tiny 2.修改下述内容 修改 set compatible 为 set nocompatible 添加 set backs ...

  2. python-加密(base64)

    import base64 #base64也是用来加密的,但是这个是可以解密的 s = "username" byte类型print(base64.b64encode(s.enco ...

  3. Struts2 Convention Plugin ( struts2 零配置 )

    Struts2 Convention Plugin ( struts2 零配置 ) convention-plugin 可以用来实现 struts2 的零配置.零配置的意思并不是说没有配置,而是通过约 ...

  4. 挣值管理(PV、EV、AC、SV、CV、SPI、CPI)

    挣值管理法中的PV.EV.AC.SV.CV.SPI.CPI这些英文简写相信把大家都搞得晕头转向的.在挣值管理法中,需要记忆理解的有三个参数:PV.AC.EV. PV:计划值,在即定时间点前计划完成活动 ...

  5. 单片机BootLoader

    http://bbs.elecfans.com/jishu_467138_1_1.html 作用:app程序,固件程序升级

  6. spring注解之@Scope

    转自:https://blog.51cto.com/4247649/2118351 作者:知了123 主要从以下几方面来介绍一下@Scope注解 @Scope注解是什么 @Scope注解怎么使用 @S ...

  7. WOJ#3882 旅行问题(POI2004)

    描述 John打算驾驶一辆汽车周游一个环形公路.公路上总共有n车站,每站都有若干升汽油(有的站可能油量为零),每升油可以让汽车行驶一千米.John必须从某个车站出发,一直按顺时针(或逆时针)方向走遍所 ...

  8. 2101 可达性统计(拓扑排序/dfs+状态压缩)

    [题目描述] 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. [题目链接] 2101 可达性统计 [算法] 拓扑排序之后逆序计算(感觉dfs更好写而且应 ...

  9. Neo4j的查询语法笔记(二)

    cypher是neo4j官网提供的声明式查询语言,非常强大,用它可以完成任意的图谱里面的查询过滤,我们知识图谱的一期项目 基本开发完毕,后面会陆续总结学习一下neo4j相关的知识.今天接着上篇文章来看 ...

  10. .net core jessetalk资料合集

    资料推荐集合贴 By Jesse • 2018-01-10 • 5064次浏览 流程图在线预览地址:https://9o90oe.axshare.com/#g=1&p=home OAuth2  ...