angular 注入器配置_Angular 4依赖注入学习教程之ValueProvider的使用(七)

学习目录

前言

本文主要给大家介绍了关于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-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> {

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: `

  • ID: {{hero.id}} - Name: {{hero.name}}

`

})

export class HeroComponent implements OnInit {

heros: Array;

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

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) { }

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值