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


Posted in Javascript onJune 04, 2017

学习目录

  • 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使用的相关内容,分享出来供大家参考学习,下面来一起详细的介绍:

本系列教程的开发环境及开发语言:

  • Angular 4 +
  • Angular CLI
  • TypeScript

基础知识

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

Javascript 相关文章推荐
javascript 浏览器检测代码精简版
Mar 04 Javascript
js获取指定的cookie的具体实现
Feb 20 Javascript
jQuery实现的支持IE的html滑动条
Mar 16 Javascript
JS实现生成会变大变小的圆环实例
Aug 05 Javascript
jQuery基于cookie实现的购物车实例分析
Dec 24 Javascript
基于jQuery实现歌词滚动版音乐播放器的代码
Sep 17 Javascript
基于JavaScript实现右键菜单和拖拽功能
Nov 28 Javascript
jquery 删除节点 添加节点 找兄弟节点的简单实现
Dec 07 Javascript
jQuery实现可拖动进度条实例代码
Jun 21 jQuery
react 父子组件之间通讯props
Sep 08 Javascript
JavaScript之解构赋值的理解
Jan 30 Javascript
JavaScript实现密码强度实时验证
Mar 18 Javascript
Angular 4依赖注入学习教程之Injectable装饰器(六)
Jun 04 #Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
Jun 04 #Javascript
JavaScript基础之this详解
Jun 04 #Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
Jun 04 #Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
Jun 04 #Javascript
Angular 4依赖注入学习教程之组件服务注入(二)
Jun 04 #Javascript
JavaScript箭头(arrow)函数详解
Jun 04 #Javascript
You might like
MySQL数据源表结构图示
2008/06/05 PHP
php获取bing每日壁纸示例分享
2014/02/25 PHP
PHP+Ajax实现无刷新分页实例详解(附demo源码下载)
2016/04/07 PHP
详解php伪造Referer请求反盗链资源
2019/01/24 PHP
prototype Element学习笔记(篇一)
2008/10/26 Javascript
快速解决jquery之get缓存问题的最简单方法介绍
2013/12/19 Javascript
jquery制作漂亮的弹出层提示消息特效
2014/12/23 Javascript
JavaScript中Function详解
2015/02/27 Javascript
js获取表格的行数和列数的方法
2015/10/23 Javascript
AngularJS模块详解及示例代码
2016/08/17 Javascript
vue.js入门教程之绑定class和style样式
2016/09/02 Javascript
jQuery实现用户输入自动完成功能
2017/02/13 Javascript
Angularjs处理页面闪烁的解决方法
2017/03/09 Javascript
Bootstrap提示框效果的实例代码
2017/07/12 Javascript
Vue.js学习笔记之修饰符详解
2017/07/25 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
使用 Vue cli 3.0 构建自定义组件库的方法
2019/04/30 Javascript
使用layui的layer组件做弹出层的例子
2019/09/27 Javascript
微信小程序连续签到7天积分获得功能的示例代码
2020/08/20 Javascript
vue项目中js-cookie的使用存储token操作
2020/11/13 Javascript
详解Python中的动态属性和特性
2018/04/07 Python
详解Python安装scrapy的正确姿势
2018/06/26 Python
Python装饰器使用你可能不知道的几种姿势
2019/10/25 Python
Python Matplotlib绘图基础知识代码解析
2020/08/31 Python
工程师必须了解的LRU缓存淘汰算法以及python实现过程
2020/10/15 Python
html5 canvas 实现光线沿不规则路径运动
2020/04/20 HTML / CSS
俄罗斯便宜的在线服装商店:GroupPrice
2020/04/10 全球购物
年会活动策划方案
2014/01/23 职场文书
工程资料员岗位职责
2014/03/10 职场文书
百年校庆节目主持词
2014/03/27 职场文书
励志演讲稿800字
2014/08/21 职场文书
买卖合同协议书范本
2014/10/18 职场文书
超市督导岗位职责
2015/04/10 职场文书
学生病假条怎么写
2015/08/17 职场文书
聊聊Python中关于a=[[]]*3的反思
2021/06/02 Python
攻略丨滑雪究竟该选哪款对讲机?
2022/02/18 无线电