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能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。