Angular 4依赖注入学习教程之ValueProvider的使用(七)
学习目录
- Angular4依赖注入教程之一依赖注入简介
- Angular4依赖注入教程之二组件服务注入
- Angular4依赖注入教程之三ClassProvider的使用
- Angular4依赖注入教程之四FactoryProvider的使用
- Angular4依赖注入教程之五FactoryProvider配置依赖对象
- Angular4依赖注入教程之六Injectable装饰器
- Angular4依赖注入教程之七ValueProvider的使用
- Angular4依赖注入教程之八InjectToken的使用
前言
本文主要给大家介绍了关于Angular4依赖注入之ValueProvider使用的相关内容,分享出来供大家参考学习,下面来一起详细的介绍:
本系列教程的开发环境及开发语言:
- Angular4+
- AngularCLI
- TypeScript
基础知识
ValueProvider的作用
ValueProvider用于告诉Injector(注入器),但使用Token获取依赖对象时,则返回useValue指定的值。
ValueProvider的使用
constprovider:ValueProvider={provide:'someToken',useValue:'someValue'};
ValueProvider接口
exportinterfaceValueProvider{ //用于设置与依赖对象关联的Token值,Token值可能是Type、InjectionToken、 //OpaqueToken的实例或字符串 provide:any; //设置注入的对象 useValue:any; //用于标识是否multipleproviders,若是multiple类型,则返回与Token关联的依赖 //对象列表 multi?:boolean; }
json-server简介
json-server用于基于JSON数据快速地创建本地模拟的RESTAPI。
json-server的安装
npminstall-gjson-server
json-server的使用
json-server--watchdb.json
AngularCLI代理配置
创建proxy.conf.json文件
{ "/heros":{ "target":"http://localhost:3000", "secure":false } }
更新package.json文件
{ "scripts":{ "start":"ngserve--proxy-configproxy.conf.json", } }
ValueProvider
介绍完基础知识,我们马上进入正题。不知道大家是否还记得,在"组件服务注入"文章中提到的内容:
难道一切就这么结束了,No!No!别忘记了我们这节课的主题是介绍如何在组件中注入服务。在目前的HeroComponent组件,我们的英雄列表信息是固定的,在实际的开发场景中,一般需要从远程服务器获取相应的信息。
接下来我们将重构我们的HeroService服务,从API接口中获取英雄数据。要使用Angular的Http服务,首先需要在AppModule模块中导入HttpModule,然后在HeroService类的构造函数中注入Http服务。
更新HeroService服务
import{Injectable}from'@angular/core'; import{Http}from'@angular/http'; import{Observable}from'rxjs/Observable'; import'rxjs/add/operator/map'; import{LoggerService}from'./logger.service'; @Injectable() exportclassHeroService{ constructor(privateloggerService:LoggerService, privatehttp:Http){} apiUrl='http://localhost:4200/heros'; getHeros():Observable>{ this.loggerService.log('Fetchingheros...'); returnthis.http.get(this.apiUrl) .map(res=>res.json()) } }
在HeroService服务中,我们通过注入Http服务对象的get()方法发送HTTP请求,从而从API接口中获取英雄的数据。
更新HeroComponent组件
import{Component,OnInit}from'@angular/core'; import{HeroService}from'../hero.service'; import{LoggerService}from'../logger.service'; @Component({ selector:'app-hero', template:`
- ID:{{hero.id}}-Name:{{hero.name}}
更新完上述代码,成功保存后,你会发现http://localhost:4200/页面,一片空白。这就对了,因为我们还没有启动本地的json-server服务器。接下来我们来配置并启动本地的json-server服务器:
创建heros.json文件
{ "heros":[ {"id":11,"name":"Mr.Nice"}, {"id":12,"name":"Narco"}, {"id":13,"name":"Bombasto"}, {"id":14,"name":"Celeritas"}, {"id":15,"name":"Magneta"} ] }
启动json-server服务器
json-server--watchheros.json
当成功启动json-server服务器,在命令行中,你将看到以下输出信息:
\{^_^}/hi! Loadingheros.json Done
这表示本地json-server已经成功启动,此时重新刷新以下http://localhost:4200/页面,你将看到以下信息:
ID:11-Name:Mr.Nice ID:12-Name:Narco ID:13-Name:Bombasto ID:14-Name:Celeritas ID:15-Name:Magneta
程序终于又正常运行了,但注意到HeroService服务中,我们通过以下方式定义API接口地址:
@Injectable() exportclassHeroService{ ... apiUrl='http://localhost:4200/heros'; }
这种方式有个问题,假设其它服务也要使用该地址,那么就得按照同样的方式去定义API接口地址。另外假设API接口地址需要更新,那就需要修改多个地方。针对上述问题,我们可以使用ValueProvider来解决问题。
使用ValueProvider
@NgModule({ ..., providers:[ { provide:'apiUrl', useValue:'http://localhost:4200/heros' } ], bootstrap:[AppComponent] }) exportclassAppModule{}
更新HeroService服务
@Injectable() exportclassHeroService{ constructor(privateloggerService:LoggerService, privatehttp:Http, @Inject('apiUrl')privateapiUrl){} getHeros():Observable>{ this.loggerService.log('Fetchingheros...'); returnthis.http.get(this.apiUrl) .map(res=>res.json()) } }
在HeroService类的构造函数中,我们通过@Inject('apiUrl')方式,注入apiUrl该Token对应的依赖对象,即'http://localhost:4200/heros'。为什么不能使用privateapiUrl:'apiUrl'的方式,希望读者好好回忆一下,之前我们介绍过的相关内容。
以上代码成功运行后,在http://localhost:4200/页面,我们将看到预期的结果:
ID:11-Name:Mr.Nice ID:12-Name:Narco ID:13-Name:Bombasto ID:14-Name:Celeritas ID:15-Name:Magneta
我有话说
为什么在构造函数中,非Type类型的参数只能用@Inject(Something)的方式注入?
因为Type类型的对象,会被TypeScript编译器编译。即我们通过class关键字声明的服务,最终都会编译成ES5的函数对象。
在构造函数中,Type类型的参数能用@Inject(Type)的方式注入么?
Type类型的参数也能使用@Inject(Type)的方式注入,具体如下:
constructor(@Inject(Http)privatehttp){}
同样也可以使用以下方式:
constructor(@Inject(Http)privatehttp:Http){}
第一种方式虽然可以正常编译,但IDE会有如下的提示信息:
[ts]Parameter'http'implicitlyhasan'any'type.
第二种方式,虽然Angular内部会合并design:paramtypes与parameters内的metadata信息,但本人觉得是有点冗余了。总而言之,若果是Type类型的参数,推荐使用下面的方式:
constructor(privatehttp:Http){}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者使用Angular4能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。