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 相关文章推荐
js设置cookie过期及清除浏览器对应名称的cookie
Oct 24 Javascript
javascript实现节点(div)名称编辑
Dec 17 Javascript
JS动态显示表格上下frame的方法
Mar 31 Javascript
jQuery实现类似淘宝网图片放大效果的方法
Jul 08 Javascript
JS实现三个层重叠点击互相切换的方法
Oct 06 Javascript
jQuery结合CSS制作动态的下拉菜单
Oct 27 Javascript
Vue.js 2.x之组件的定义和注册图文详解
Jun 19 Javascript
node.js学习笔记之koa框架和简单爬虫练习
Dec 13 Javascript
JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例
Dec 14 Javascript
gulp构建小程序的方法步骤
May 31 Javascript
微信小程序实现传递多个参数与事件处理
Aug 12 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
Jul 22 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
PHP图片处理之使用imagecopy函数添加图片水印实例
2014/11/19 PHP
PHP生成短网址方法汇总
2016/07/12 PHP
Laravel 5.3 学习笔记之 错误&amp;日志
2016/08/28 PHP
PHP策略模式定义与用法示例
2017/07/27 PHP
php数组和链表的区别总结
2019/09/20 PHP
PHP使用Http Post请求发送Json对象数据代码解析
2020/07/16 PHP
JavaScript中OnLoad几种使用方法
2012/12/15 Javascript
js截取小数点后几位的写法
2013/11/14 Javascript
document.forms[].submit()使用介绍
2014/02/19 Javascript
Javascript中的delete操作符详细介绍
2014/06/06 Javascript
原生javascript获取元素样式
2014/12/31 Javascript
深入分析JSON编码格式提交表单数据
2015/06/25 Javascript
理解JavaScript事件对象
2016/01/25 Javascript
Angularjs material 实现搜索框功能
2016/03/08 Javascript
Angular的MVC和作用域
2016/12/26 Javascript
写jQuery插件时的注意点
2017/02/20 Javascript
vue-resourse将json数据输出实例
2017/03/08 Javascript
vue中v-model动态生成的实例详解
2017/10/27 Javascript
vue2.0学习之axios的封装与vuex介绍
2018/05/28 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
2018/07/03 Javascript
vue的.vue文件是怎么run起来的(vue-loader)
2018/12/10 Javascript
koa中间件核心(koa-compose)源码解读分析
2020/06/15 Javascript
Python学习笔记_数据排序方法
2014/05/22 Python
python 捕获shell脚本的输出结果实例
2017/01/04 Python
Python中创建字典的几种方法总结(推荐)
2017/04/27 Python
Python三级菜单的实例
2017/09/13 Python
pandas使用get_dummies进行one-hot编码的方法
2018/07/10 Python
opencv调整图像亮度对比度的示例代码
2019/09/27 Python
如何基于python生成list的所有的子集
2019/11/11 Python
Python线程协作threading.Condition实现过程解析
2020/03/12 Python
pycharm无法安装第三方库的问题及解决方法以scrapy为例(图解)
2020/05/09 Python
css3边框_动力节点Java学院整理
2017/07/11 HTML / CSS
移动端Html5页面生成图片解决方案
2018/08/07 HTML / CSS
后勤工作个人总结
2015/02/28 职场文书
靠谱的活动总结
2019/04/16 职场文书
Echarts如何重新渲染实例详解
2022/05/30 Javascript