欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Angular 4依赖注入学习教程之ValueProvider的使用(七)

程序员文章站 2022-07-05 20:38:08
学习目录 angular 4 依赖注入教程之一 依赖注入简介 angular 4 依赖注入教程之二 组件服务注入 angular 4 依赖注入教程...

学习目录

前言

本文主要给大家介绍了关于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能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。