Angular:ViewProviders和Providers的区别

摘要:
在Angular中使用依赖注入时,我们通常使用提供程序。事实上,我们还有另一个选择来做同样的事情:viewProviders。ViewProviders允许我们定义仅对组件视图可见的提供程序`})exportclassViewVPChild{constructor{this.service.testIfGetService;}}这里还注入MyService服务,调用MyService服务的testIfGetServices方法,并传入viewChild`,viewProviders:[MyService]//<--})exportclassVPParent{constructor{this.service.testIfGetService;}}}}修改后,运行程序并发现错误:如果注释掉contentChild,它看起来像这样:˂----˃不会报告错误:这意味着在父组件中向viewProviders注册的提供程序对contentChildren不可见。

在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>

运行程序,控制台打印出了结果:
Angular:ViewProviders和Providers的区别第1张

一切就像预期那样!!
然后,我们用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');
  }
}

这样修改之后,运行程序,发现报错了:
Angular:ViewProviders和Providers的区别第2张

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

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

是不会报错的:
Angular:ViewProviders和Providers的区别第3张

这就说明,在父组件用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的区别》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用ATOMac进行Mac自动化测试Unity Mathf/Math 数学运算函数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

angular写的一个导航栏

ts import { Component } from '@angular/core'; // 定义一个interface interface Menu{ title:string,link:string,id:string } @Component({ selector: 'app-root', templateUrl: './app.co...

Angular Scope解析与应用

Scope层级结构 顶层服务对象$rootScope来源于ng模块。由$RootScopeProvider提供。 由于ng模块是angular.bootstrap()运行时依赖的模块,所以在整个应用中都能够通过$rootScope引用,并且在这个应用中是唯一的。但唯一性仅限于单个应用内,由于服务都存在注入器中,而每一个bootstrap应用有自己的注...

基于AngularJs的上传控件-angular-file-upload

今天跟大家分享的是一个依赖于angular的上传控件。 前段时间做项目遇到一个需求是上传文件,大概需要实现的样式是这样子的,见下图: 需要同时上传两个文件。并且规定文件格式和文件大小。因为前端框架使用angular,且不想因为一个上传功能又引入一个jquery,所以在网上查找基于angular的上传控件,因为angular还算比较新,貌似都没有太成熟的插...

UI组件库Kendo UI for Angular入门指南教程

Conversational UI组件弥合了Web 和下一代自然语言应用程序之间的差距。Conversational UI 包提供了Kendo UI聊天组件,该组件允许用户参与与其他用户或聊天机器人的聊天会话。 Conversational UI Package 是Kendo UI for Angular的一部分,这是一个专业级 UI 库,具有 100 多...

AngularJS学习笔记(一) 关于MVVM和双向绑定

写在前面:      因为需要开始学习ng,之前在知乎上听大神们介绍ng的时候说这个坑如何的大,学了一阵(其实也就三天),感觉ng做的很大很全,在合适的情境你可以完全使用ng搞定一切。这一点从诸如jqLite之类的鸡肋就能看出来了。所以搞得ng很大。。     更主要的是,ng用一种和之前完全不同的思维方式去组织代码,它就是Model-View-ViewM...

angular 依赖注入

依赖注入    依赖注入(DI)是一个经典的设计模式, 主要是用来处理组件如何获得依赖的问题。关于DI,推荐阅读Martin Flower的文章(http://martinfowler.com/articles/injection.html )。    Angular负责创建组件,解决它们之间的依赖关系,并按要求提供其他组件。 使用依赖注入   依赖注入在...