乐趣区

关于angular:Angular-依赖注入学习笔记之工厂函数的用法

网址:https://angular.institute/di

We can transfer any data through our apps, transform it and replace it.

咱们能传递任何数据到咱们的利用里,扭转其状态,并且替换。

Another case: document and fetch can work in your browser correctly. But one day you need to build your app in SSR or precompile with nodejs. Global entities might be missing or be different in that environment.

document 和 fetch 能在浏览器环境下运行。然而如果在 SSR 下 build 利用,或者用 nodejs precompile,那么这些对象在新的环境下不再可用。

Dependency Injection mechanism manages dependencies in your application. For you as an Angular developer, it is a straightforward instrument. There are two operations: you can provide something into your DI tree or take something from it.

依赖注入机制治理利用的依赖。对于 Angular 开发者来说,有两种操作:

  1. 提供数据到依赖注入树中
  2. 从依赖注入树中获取数据

The magic is the order in which you provide and take your dependencies.
Angular creates a class instance when you ask for this the first time.

当咱们试图在 DI 树里第一次获取实例时,Angular 负责实例化。

Providing value is normally used with InjectionToken. This object is like a key for DI mechanism.

咱们也能够用依赖注入提供常量,通常借助 InjectionToken. 这个令牌相似依赖注入机制中的 key.

You say “I want to get this data with this key” and ask DI in a component “Do you have something for this key?”

咱们应用 InjectionToken 作为 key,询问 Angular 依赖注入机制,“你保护的资源里,有针对这个 key 的值吗?”

看个具体的例子。

export const API_URL = new InjectionToken<string>('The URL of API');

在 api-url.token.ts 里,咱们从 @angular/core 里导入了规范的 InjectionToken 结构器,其类型为 string,形容信息为:The URL of API.

在 app.module.ts 里,导入这个 API_URL token,而后在 module 的 NgModule 注解里,应用 useValue 提供 token key 代表的具体值:

如何应用这个 token 呢?参考下图代码:

export class AppComponent  {constructor(@Inject(API_URL) readonly apiUrl: string) {
    /**
     * Here we asked for something with a key API_URL.
     * There is our string in DI and we get it
     */
    console.log(apiUrl);
  }
}

语义就是,在 app Component 里,应用 @Inject 注解,向 DI 树里查问,是否存在 key 为 API_URL 的注入值。

  • We can replace token value at any level of DI tree without any changes in a component – 咱们能够在 DI 树上的任意层次结构里,替换 token 的值,而不须要批改 Component
  • We can mock a token value providing suitable data in tests – 在测试代码里,咱们能够 mock 一个 token 值
  • The component class is fully isolated and can be used without any context

Providing a factory

这是 Angular 依赖注入的高级用法之一。

You can provide some value combining and transforming data from other tokens.

咱们能够在 factory 代码里编写一些业务逻辑,执行一些数据结构变换的操作。

看个例子:

定义一个函数:

import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";

import {AppComponent} from "./app.component";
import {PRESSED_KEY} from "./tokens/pressed-key";
import {Observable, fromEvent} from "rxjs";
import {map} from "rxjs/operators";
import {DOCUMENT} from "@angular/common";

/**
 * It is a token value factory.
 *
 * The factory is called when app.component.ts asks for
 * the token PRESSED_KEY the first time
 */
function pressedKeyFactory(documentRef: Document): Observable<string> {return fromEvent(documentRef.body, "keydown").pipe(map((event: KeyboardEvent) => event.key)
  );
}

结构一个 Observable 对象,当键盘被按下时,从 KeyboardEvent 里解析出具体哪一个键被按下,而后将 key 值通过 Observable 对象返回。

这个函数被当成一个工厂函数,自身接管类型为 Document 的参数,这个参数就是其依赖。

咱们通过下列的语法,将名为 PRESSED_KEY 的令牌,和该工厂函数绑定在一起。

@NgModule({imports: [BrowserModule, FormsModule],
  declarations: [AppComponent],
  bootstrap: [AppComponent],
  providers: [
    {
      provide: PRESSED_KEY,
      /**
       * Here you can provide any token and its value will be injected
       * as a factory function argument
       */
      deps: [DOCUMENT],
      useFactory: pressedKeyFactory
    }
  ]
})

该 token 的生产形式:

更多 Jerry 的原创文章,尽在:” 汪子熙 ”:

退出移动版