ValueProvider的使用

阅读须知

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

基础知识

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') 方式,注入 apiUrlToken 对应的依赖对象,即 '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 这篇文章。


上一篇:Injectable装饰器
下一篇:InjectToken的使用