【问题标题】:Angular 5 service replacement/overrideAngular 5 服务替换/覆盖
【发布时间】:2018-10-02 05:27:27
【问题描述】:

我为我的项目创建了一个包含一些组件和服务的核心库。我用 ng-packagr 构建了这个库。在引用库的消费项目中,我构建了包含库提供的组件的 web 应用程序。到目前为止没有什么特别的。但有时我想要一个组件(来自我的库)从库外的服务调用方法。这可能吗?我可以以某种方式向库中定义的组件注入服务吗?

干杯

【问题讨论】:

  • 您是否在询问您图书馆的消费者是否可以为您的图书馆提供不同的服务供您使用?
  • 是的,我们知道 Angular 都是由模块构建的。要让您的组件与在另一个模块(库)中声明的另一个服务/组件对话,该模块需要在您的模块中导入(包含您希望与外部服务/模块对话的组件)。这正是您使用 httpClient 等标准 Angular 服务的方式。
  • @Daniel W Strimpel。基本上是的。我想外包一个库中的核心组件和服务。我引用了这个库,因此引用了另一个项目中的组件。有时我希望引用的组件使用自定义服务而不是原始引用的服务(也是 lib 的一部分)。
  • 研究在你的模块上使用forRoot方法来提供配置信息。

标签: javascript angular angular-cli angular5 ng-packagr


【解决方案1】:

我之前已经通过类似的方式实现了这一点:

你的库的服务应该被定义为一个接口而不是一个具体的实现(就像在 OO 语言中经常做的那样)。如果您的实现应用程序有时只想传入它自己的服务版本,那么您应该在您的库中创建一个默认服务,并像这样使用它:

import { Component, NgModule, ModuleWithProviders, Type, InjectionToken, Inject, Injectable } from '@angular/core';

export interface ILibService {
  aFunction(): string;
}

export const LIB_SERVICE = new InjectionToken<ILibService>('LIB_SERVICE');

export interface MyLibConfig {
  myService: Type<ILibService>;
}

@Injectable()
export class DefaultLibService implements ILibService {
  aFunction() {
    return 'default';
  }
}

@Component({
  // whatever
})
export class MyLibComponent {
  constructor(@Inject(LIB_SERVICE) libService: ILibService) {
    console.log(libService.aFunction());
  }
}

@NgModule({
  declarations: [MyLibComponent],
  exports: [MyLibComponent]
})
export class LibModule {
  static forRoot(config?: MyLibConfig): ModuleWithProviders {
    return {
      ngModule: LibModule,
      providers: [
        { provide: LIB_SERVICE, useClass: config && config.myService || DefaultLibService }
      ]
    };
  }
}

然后在您的实现应用程序中,您可以通过库的forRoot 方法传入可选配置(​​注意forRoot 每个应用程序只应调用一次,并尽可能在最高级别调用)。请注意,我已将 config 参数标记为可选参数,因此即使您没有要传递的配置,您也应该调用 forRoot

import { NgModule, Injectable } from '@angular/core';
import { LibModule, ILibService } from 'my-lib';

@Injectable()
export class OverridingService implements ILibService {
  aFunction() {
    return 'overridden!';
  }
}

@NgModule({
  imports: [LibModule.forRoot({ myService: OverridingService })]
})
export class ImplementingModule {

}

这是凭记忆写的,因为我目前手头没有代码,所以如果由于任何原因它不起作用,请告诉我。

【讨论】:

  • 嘿,我试过了,效果很好。我只有一个问题:默认服务没有提供者 :) 我只是将它添加到库模块的提供列表中。其余的工作,因此我将此答案设置为我的问题的解决方案。再次感谢。
  • 你不应该将它添加到提供者列表中,forRoot 会处理这个问题。我错过了服务上的 @Injectable() 装饰器 - 这应该是问题所在。
  • 不幸的是,我收到了同样的问题,即使在两个服务上都使用 @Injectable() :(
  • 你能告诉我你在哪里导入模块和确切的错误信息吗?
  • 在我的回答中查看MyLibComponent - 看到它期望ILibService 被注入,而不是具体类DefaultLibService 那是CustomFlowAComponent 中的问题
猜你喜欢
  • 2016-07-09
  • 1970-01-01
  • 2018-08-25
  • 2014-01-09
  • 2019-11-07
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多