淘先锋技术网

首页 1 2 3 4 5 6 7

        第一步,关于一些概念,看看大佬的写的。👉  Angular Provider

        angular的provider, 就是把一些可复用的逻辑,或者外部请求等,从组件里面抽出来,放到一个单独的class里面,方便多个组件或指令等共享。假如不用angular的依赖注入,自己写需要手动实例化service, 比如这样:

// service
class Hello {
    say () {
        console.log(' Hello !');
    }
}

// componnet
import {Hello} from 'XXX/Hello.ts';
class DemoComponent {
    hello = null;
    constrctor() {
        // 重点在这里
        this.hello = new Hello();
    }
}

        Angular 的注册器,负责实例化依赖并注入到需要的组件(或者指令什么的)中。

        Angular注册器什么时候创建的呢?在应用启动的时候,Angular会创建两个注册器树。一个是为模块服务的模块注册器树,另一个是元素注册器树 (组件、指令等)。应用加载的时候会加载更模块(名字叫做AppModule), 它为根模块 创建 根模块注册器,这个注册器具有整个应用范围的作用域。根模块注册器是注册器树的一部分。根模块加载应用的根组件-AppComponent,这个组件有它自己的注册器,叫做root injector, 这个注册器是元素注册器树的一部分。

        关于,DI Token . 就是providers配置对象的‘provider’key,是angular确定咱们代码里面用的时候用哪个provider.  如果 provide 和 useClass一样,可以简写为我们常见的那样。

// DI Token - injection 
import { InjectionToken } from '@angular/core'; 
export const APIURL = new InjectionToken<string>('');

@NgModule({
   providers: [
    {
        provide: 'API', // DI Token - string
        useValue: '123'
    },
    { provide: APIURL, useValue: 'http://xxx/get'}
    {
        provide: HelloService, // DI Token - class
        useClass: FakeHelloService
    },    
    // 如果 provide ,useClass一样
    MessageService 
  ],
});


// Demo Componnet
export class DemoComponent {
  // string and injection token need use @inject to 调用invoke
  constructor(
    @Inject(APIURL) public ApiUrl: String,
    private hello: HelloService
  ) { }
}

关于 multi: true.

如果是true,注入器返回一个实例数组。这对于允许多个提供者跨多个文件向公共令牌提供配置信息非常有用。(啥意思?)

--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--🍒--     

         然后,列举一下几种provider吧。

        export declare type Provider = TypeProvider |  ValueProvider | ClassProvider |  ConstructorProvider |  ExistingProvider | FactoryProvider |  any[];

        1) ValueProvider:        

// 注册
@NgModule({
    providers:  [
        {provider: 'LOGIN_API', useValue: '/login'},    
    ]
})
export class AppModule {}

// 消费
export class DemoComponent {
    constructor ( 
        @Inject('LOGIN_API') public login_api: string
    ) {}
}

        2) ClassProvider

@NgModule({
    providers:  [
        // 不一样
        {provider: HelloService, useClass: FakeHelloService}, 
        // 一样
        {provider: HelloService, useClass: HelloService}, 
        HelloService,
    ]
})
export class AppModule {}

       3)  FactoryProvider:  

interface FactoryProvider extends FactorySansProvider {
  provide: any
  // 如果为 true,则注入器返回实例数组。
  // 这对于允许多个提供者散布在多个文件中,以向某个公共令牌提供配置信息很有用。?啥意思
  multi?: boolean

  // 继承自 core/FactorySansProvider
  useFactory: Function
  deps?: any[]
}


@NgModule({
    providers:  [
        LoggerService,
        {
            provide: MessageService,
            useFactory: (atoken,anothertoken) => {
                // 返回普通值,和 ValueProvider差不多了
                // return '/list'
                // 根据某些条件判断,返回哪个service实例。 
                // 比如已经写个两个service, Hello, Message
                let condition = true;
                return  condition ? new Hello() : new Message();
            },
            // deps是给useFactory的DI token 列表
            deps: [LoggerService],
            multi: false 
        }
    ]
})
export class AppModule {}

           4) ExistingProvider:

                providers: [    
                    // 实际上,组件里面用的Hello,是Message
                    { provide: HelloService, useExisting: FakeHelloService },
                    { provide: FakeHelloService, useClass:MessageService },
                ]

        tips: provide 的参数是DI Token, DI Token有好几种,为了方便,demo使用了其中的class形式。useExistingd的参数也是DI Token.

         5) ConstructorProvider:

// 简写了,只写了关键代码


// appModule
providers = [
    {
      provide: 'API',
      useValue: '/login'
    },
    {
      provide: MyService,
      deps: ['API']
    }
]
 

// MyService
export class MyService {

  constructor(
    @Inject('API') public api: string
  ) { }

  getApi() {
    return this.api;
  }

}

// demo component
class DemoComponent {
    constructor(
        private ms: MyServiceService
    ) {
        console.log(this.ms.getApi()); // '/login'
    }
}

       6) TypeProvider 

        这个...