阅读须知
本系列教程的开发环境及开发语言:
基础知识
ValueProvider 的作用
ValueProvider 用于告诉 Injector (注入器),但使用 Token
获取依赖对象时,则返回 useValue
指定的值。
ValueProvider 的使用
----- --------- ------------- - --------- ------------ --------- -------------
ValueProvider 接口
------ --------- ------------- - -- ------------------------------------------------ -- ------------------ -------- ---- -- ------- --------- ---- -- -------------- ------------------------------------- -- ---- ------- -------- -
json-server 简介
json-server 用于基于 JSON 数据快速地创建本地模拟的 REST
API。
json-server 的安装
--- ------- -- -----------
json-server 的使用
----------- ------- -------
Angular CLI 代理配置
创建 proxy.conf.json
文件
- --------- - --------- ------------------------ --------- ----- - -
更新 package.json
文件
- ---------- - -------- --- ----- -------------- ----------------- - -
ValueProvider
介绍完基础知识,我们马上进入正题。不知道大家是否还记得,在 "组件服务注入" 文章中提到的内容:
难道一切就这么结束了,No! No!别忘记了我们这节课的主题是介绍如何在组件中注入服务。在目前的
HeroComponent
组件,我们的英雄列表信息是固定的,在实际的开发场景中,一般需要从远程服务器获取相应的信息。
接下来我们将重构我们的 HeroService
服务,从 API 接口中获取英雄数据。要使用 Angular 的 Http
服务,首先需要在 AppModule
模块中导入 HttpModule
,然后在 HeroService
类的构造函数中注入 Http
服务。
更新 HeroService 服务
------ - ---------- - ---- ---------------- ------ - ---- - ---- ---------------- ------ - ---------- - ---- ------------------ ------ ------------------------ ------ - ------------- - ---- ------------------- ------------- ------ ----- ----------- - ------------------- -------------- -------------- ------- ----- ----- - - ------ - ------------------------------ ----------- ------------------ ------ ---------- -------- --------- ------ - -------------------------------- ----------- ------ -------------------------- -------- -- ----------- - -
</Array<{>
在 HeroService
服务中,我们通过注入 Http
服务对象的 get()
方法发送 HTTP
请求,从而从 API
接口中获取英雄的数据。
更新 HeroComponent 组件
------ - ---------- ------ - ---- ---------------- ------ - ----------- - ---- ------------------ ------ - ------------- - ---- -------------------- ------------ --------- ----------- --------- - ---- --- ----------- ---- -- ------- --- ----------- - ----- ------------- ----- ----- - -- ------ ----- ------------- ---------- ------ - ------ ------- ------ ---------- -------- --------- ------ ------------------- ------------ ------------ ------- -------------- -------------- - - ---------- - -------------------------------- ----------- --------------------------- -------------- -- - ---------- - ---- --- - -
</{>
更新完上述代码,成功保存后,你会发现 http://localhost:4200/
页面,一片空白。这就对了,因为我们还没有启动本地的 json-server
服务器。接下来我们来配置并启动本地的 json-server
服务器:
创建 heros.json
文件
- -------- - -------------------- ------- ------------------------- ---------------------------- ----------------------------- -------------------------- - -
启动 json-server
服务器
----------- ------- ----------
当成功启动 json-server
服务器,在命令行中,你将看到以下输出信息:
------- --- ------- ---------- ----
这表示本地 json-server
已经成功启动,此时重新刷新以下 http://localhost:4200/
页面,你将看到以下信息:
--- -- - ----- --- ---- --- -- - ----- ----- --- -- - ----- -------- --- -- - ----- --------- --- -- - ----- -------
程序终于又正常运行了,但注意到 HeroService
服务中,我们通过以下方式定义 API
接口地址:
------------- ------ ----- ----------- - --- ------ - ------------------------------ -
这种方式有个问题,假设其它服务也要使用该地址,那么就得按照同样的方式去定义 API
接口地址。另外假设 API
接口地址需要更新,那就需要修改多个地方。针对上述问题,我们可以使用 ValueProvider
来解决问题。
使用 ValueProvider
----------- ---- ---------- - - -------- --------- --------- ----------------------------- - -- ---------- -------------- -- ------ ----- --------- - -
更新 HeroService 服务
------------- ------ ----- ----------- - ------------------- -------------- -------------- ------- ----- ----- ----------------- ------- ------- - - ----------- ------------------ ------ ---------- -------- --------- ------ - -------------------------------- ----------- ------ -------------------------- -------- -- ----------- - -
</Array<{>
在 HeroService
类的构造函数中,我们通过 @Inject('apiUrl')
方式,注入 apiUrl
该 Token
对应的依赖对象,即 'http://localhost:4200/heros'
。为什么不能使用 private apiUrl: 'apiUrl'
的方式,希望读者好好回忆一下,之前我们介绍过的相关内容。
以上代码成功运行后,在 http://localhost:4200/
页面,我们将看到预期的结果:
--- -- - ----- --- ---- --- -- - ----- ----- --- -- - ----- -------- --- -- - ----- --------- --- -- - ----- -------
我有话说
为什么在构造函数中,非 Type 类型的参数只能用 @Inject(Something) 的方式注入 ?
因为 Type
类型的对象,会被 TypeScript
编译器编译。即我们通过 class
关键字声明的服务,最终都会编译成 ES5
的函数对象。
在构造函数中,Type 类型的参数能用 @Inject(Type) 的方式注入么?
Type
类型的参数也能使用 @Inject(Type)
的方式注入,具体如下:
------------------------- ------- ----- - -
同样也可以使用以下方式:
------------------------- ------- ----- ----- - -
第一种方式虽然可以正常编译,但 IDE 会有如下的提示信息:
---- --------- ------ ---------- --- -- ----- -----
第二种方式,虽然 Angular 内部会合并 design:paramtypes 与 parameters 内的 metadata 信息,但本人觉得是有点冗余了。 总而言之,若果是 Type 类型的参数,推荐使用下面的方式:
------------------- ----- ----- - -
若有兴趣了解 Inject
装饰器的详细信息,请参考 Angular 2 Inject 这篇文章。