Angular 4依赖注入学习教程之ValueProvider的使用(七)
学习目录
- angular 4 依赖注入教程之一 依赖注入简介
- angular 4 依赖注入教程之二 组件服务注入
- angular 4 依赖注入教程之三 classprovider的使用
- angular 4 依赖注入教程之四 factoryprovider的使用
- angular 4 依赖注入教程之五 factoryprovider配置依赖对象
- angular 4 依赖注入教程之六 injectable 装饰器
- angular 4 依赖注入教程之七 valueprovider的使用
- angular 4 依赖注入教程之八 injecttoken的使用
前言
本文主要给大家介绍了关于angular 4依赖注入之valueprovider使用的相关内容,分享出来供大家参考学习,下面来一起详细的介绍:
本系列教程的开发环境及开发语言:
基础知识
valueprovider 的作用
valueprovider 用于告诉 injector (注入器),但使用 token 获取依赖对象时,则返回 usevalue 指定的值。
valueprovider 的使用
const provider: valueprovider = {provide: 'sometoken', usevalue: 'somevalue'};
valueprovider 接口
export interface valueprovider { // 用于设置与依赖对象关联的token值,token值可能是type、injectiontoken、 // opaquetoken的实例或字符串 provide: any; // 设置注入的对象 usevalue: any; // 用于标识是否multiple providers,若是multiple类型,则返回与token关联的依赖 // 对象列表 multi?: boolean; }
json-server 简介
用于基于 json 数据快速地创建本地模拟的 rest api。
json-server 的安装
npm install -g json-server
json-server 的使用
json-server --watch db.json
angular cli 代理配置
创建 proxy.conf.json 文件
{ "/heros": { "target": "http://localhost:3000", "secure": false } }
更新 package.json 文件
{ "scripts": { "start": "ng serve --proxy-config proxy.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() export class heroservice { constructor(private loggerservice: loggerservice, private http: http) { } apiurl = 'http://localhost:4200/heros'; getheros(): observable<array<{ id: number; name: string }>> { this.loggerservice.log('fetching heros...'); return this.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: ` <ul> <li *ngfor="let hero of heros"> id: {{hero.id}} - name: {{hero.name}} </li> </ul> ` }) export class herocomponent implements oninit { heros: array<{ id: number; name: string }>; constructor(private heroservice: heroservice, private loggerservice: loggerservice) { } ngoninit() { this.loggerservice.log('fetching heros...'); this.heroservice.getheros() .subscribe(res => { this.heros = res; }); } }
更新完上述代码,成功保存后,你会发现 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 --watch heros.json
当成功启动 json-server 服务器,在命令行中,你将看到以下输出信息:
\{^_^}/ hi! loading heros.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() export class heroservice { ... apiurl = 'http://localhost:4200/heros'; }
这种方式有个问题,假设其它服务也要使用该地址,那么就得按照同样的方式去定义 api 接口地址。另外假设 api 接口地址需要更新,那就需要修改多个地方。针对上述问题,我们可以使用 valueprovider 来解决问题。
使用 valueprovider
@ngmodule({ ..., providers: [ { provide: 'apiurl', usevalue: 'http://localhost:4200/heros' } ], bootstrap: [appcomponent] }) export class appmodule { }
更新 heroservice 服务
@injectable() export class heroservice { constructor(private loggerservice: loggerservice, private http: http, @inject('apiurl') private apiurl) { } getheros(): observable<array<{ id: number; name: string }>> { this.loggerservice.log('fetching heros...'); return this.http.get(this.apiurl) .map(res => res.json()) } }
在 heroservice 类的构造函数中,我们通过 @inject('apiurl')
方式,注入 apiurl 该 token 对应的依赖对象,即 'http://localhost:4200/heros' 。为什么不能使用 private apiurl: '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) private http) { }
同样也可以使用以下方式:
constructor(@inject(http) private http: http) { }
第一种方式虽然可以正常编译,但 ide 会有如下的提示信息:
[ts] parameter 'http' implicitly has an 'any' type.
第二种方式,虽然 angular 内部会合并 design:paramtypes
与 parameters 内的 metadata 信息,但本人觉得是有点冗余了。 总而言之,若果是 type 类型的参数,推荐使用下面的方式:
constructor(private http: http) { }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者使用angular 4能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
推荐阅读
-
Angular 4依赖注入学习教程之ClassProvider的使用(三)
-
Angular 4依赖注入学习教程之ValueProvider的使用(七)
-
Angular 4依赖注入学习教程之InjectToken的使用(八)
-
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
-
Angular 4依赖注入学习教程之ValueProvider的使用(七)
-
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
-
Angular 4依赖注入学习教程之InjectToken的使用(八)
-
Angular 4依赖注入学习教程之ClassProvider的使用(三)